英文:
serde: Deserialize `str` in Rust
问题
The error message indicates that the Deserialize
trait is not implemented for str
, but it is implemented for &'a str
. To address this issue without modifying TypePath
in main.rs
, you can provide a custom implementation of Deserialize
for Cou<'a, str>
in the cou.rs
file. Here's a potential solution:
use serde::{Deserialize, Deserializer, Serialize};
#[derive(Serialize)]
pub enum Cou<'a, T>
where
T: ToOwned + ?Sized,
{
Borrowed(&'a T),
Upgraded(std::sync::Arc<T::Owned>),
}
impl<'de> Deserialize<'de> for Cou<'de, str> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
// Deserialize `&str` from the provided deserializer and create a `Cou::Borrowed`.
let s: &'de str = Deserialize::deserialize(deserializer)?;
Ok(Cou::Borrowed(s))
}
}
This code provides a custom Deserialize
implementation for Cou<'a, str>
by deserializing a &str
and wrapping it in Cou::Borrowed
. This way, you can handle the deserialization of str
without modifying the main.rs
code.
英文:
I am working on an existing codebase in Rust, wherein I need to serialize/deserialize a struct with a <'a, str>
type.
I am mentioning the minimal reproducible snippets here:
File: main.rs
use serde::{Deserialize, Serialize};
use crate::cou::Cou;
#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
pub struct TypePath<'a>(Vec<Cou<'a, str>>);
File: cou.rs
use std::{
borrow::Borrow,
sync::Arc,
};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
pub enum Cou<'a, T>
where
T: ToOwned + ?Sized,
{
Borrowed(&'a T),
Upgraded(Arc<T::Owned>),
}
When I build the above, it gives an error:
error[E0277]: the trait bound `str: Deserialize<'_>` is not satisfied
--> src/ast.rs:136:25
|
136 | pub struct TypePath<'a>(Vec<Cou<'a, str>>);
| ^^^ the trait `Deserialize<'_>` is not implemented for `str`
|
= help: the trait `Deserialize<'de>` is implemented for `&'a str`
note: required for `Cou<'a, str>` to implement `Deserialize<'_>`
--> src/cou.rs:11:21
|
11 | #[derive(Serialize, Deserialize)]
| ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
12 | pub enum Cou<'a, T>
| ^^^^^^^^^^
= note: 1 redundant requirement hidden
= note: required for `Vec<Cou<'a, str>>` to implement `Deserialize<'_>`
= note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info)
Now the output says that the trait is implemented for &'a str
but I do not want to change TypePath in main.rs as it is used widely in the remainder of the codebase. Is it possible to define Deserialize
for str
?
答案1
得分: 2
Cou
与Cow
具有相同的结构,因此您几乎可以从serde的实现中进行复制粘贴。
use std::{sync::Arc};
use std::borrow::Borrow;
use std::ops::Deref;
use serde::{Deserializer, Deserialize, Serializer, Serialize};
pub enum Cou<'a, T>
where
T: ToOwned + ?Sized,
{
Borrowed(&'a T),
Upgraded(Arc<T::Owned>),
}
impl<B: ?Sized + ToOwned> Deref for Cou<'_, B>
where
B::Owned: Borrow<B>,
{
type Target = B;
fn deref(&self) -> &B {
match *self {
Cou::Borrowed(borrowed) => borrowed.borrow(),
Cou::Upgraded(ref owned) => owned.deref().borrow(),
}
}
}
impl<'a, T: ?Sized> Serialize for Cou<'a, T> where T: Serialize + ToOwned {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
(**self).serialize(serializer)
}
}
impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cou<'a, T>
where
T: ToOwned,
T::Owned: Deserialize<'de>,
{
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
T::Owned::deserialize(deserializer).map(Arc::new).map(Cou::Upgraded)
}
}
英文:
Cou
has the same structure as Cow
, so you can almost copy-paste ser/de implementations from serde.
use std::{sync::Arc};
use std::borrow::Borrow;
use std::ops::Deref;
use serde::{Deserializer, Deserialize, Serializer, Serialize};
pub enum Cou<'a, T>
where
T: ToOwned + ?Sized,
{
Borrowed(&'a T),
Upgraded(Arc<T::Owned>),
}
impl<B: ?Sized + ToOwned> Deref for Cou<'_, B>
where
B::Owned: Borrow<B>,
{
type Target = B;
fn deref(&self) -> &B {
match *self {
Cou::Borrowed(borrowed) => borrowed.borrow(),
Cou::Upgraded(ref owned) => owned.deref().borrow(),
}
}
}
impl <'a, T: ?Sized> Serialize for Cou<'a, T> where T: Serialize + ToOwned {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
(**self).serialize(serializer)
}
}
impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cou<'a, T>
where
T: ToOwned,
T::Owned: Deserialize<'de>,
{
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
T::Owned::deserialize(deserializer).map(Arc::new).map(Cou::Upgraded)
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论