serde: 在Rust中反序列化`str`

huangapple go评论99阅读模式
英文:

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:

  1. use serde::{Deserialize, Deserializer, Serialize};
  2. #[derive(Serialize)]
  3. pub enum Cou<'a, T>
  4. where
  5. T: ToOwned + ?Sized,
  6. {
  7. Borrowed(&'a T),
  8. Upgraded(std::sync::Arc<T::Owned>),
  9. }
  10. impl<'de> Deserialize<'de> for Cou<'de, str> {
  11. fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  12. where
  13. D: Deserializer<'de>,
  14. {
  15. // Deserialize `&str` from the provided deserializer and create a `Cou::Borrowed`.
  16. let s: &'de str = Deserialize::deserialize(deserializer)?;
  17. Ok(Cou::Borrowed(s))
  18. }
  19. }

This code provides a custom Deserialize implementation for Cou&lt;&#39;a, str&gt; 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 &lt;&#39;a, str&gt; type.

I am mentioning the minimal reproducible snippets here:

File: main.rs

  1. use serde::{Deserialize, Serialize};
  2. use crate::cou::Cou;
  3. #[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
  4. pub struct TypePath&lt;&#39;a&gt;(Vec&lt;Cou&lt;&#39;a, str&gt;&gt;);

File: cou.rs

  1. use std::{
  2. borrow::Borrow,
  3. sync::Arc,
  4. };
  5. use serde::{Deserialize, Serialize};
  6. #[derive(Serialize, Deserialize)]
  7. pub enum Cou&lt;&#39;a, T&gt;
  8. where
  9. T: ToOwned + ?Sized,
  10. {
  11. Borrowed(&amp;&#39;a T),
  12. Upgraded(Arc&lt;T::Owned&gt;),
  13. }

When I build the above, it gives an error:

  1. error[E0277]: the trait bound `str: Deserialize&lt;&#39;_&gt;` is not satisfied
  2. --&gt; src/ast.rs:136:25
  3. |
  4. 136 | pub struct TypePath&lt;&#39;a&gt;(Vec&lt;Cou&lt;&#39;a, str&gt;&gt;);
  5. | ^^^ the trait `Deserialize&lt;&#39;_&gt;` is not implemented for `str`
  6. |
  7. = help: the trait `Deserialize&lt;&#39;de&gt;` is implemented for `&amp;&#39;a str`
  8. note: required for `Cou&lt;&#39;a, str&gt;` to implement `Deserialize&lt;&#39;_&gt;`
  9. --&gt; src/cou.rs:11:21
  10. |
  11. 11 | #[derive(Serialize, Deserialize)]
  12. | ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
  13. 12 | pub enum Cou&lt;&#39;a, T&gt;
  14. | ^^^^^^^^^^
  15. = note: 1 redundant requirement hidden
  16. = note: required for `Vec&lt;Cou&lt;&#39;a, str&gt;&gt;` to implement `Deserialize&lt;&#39;_&gt;`
  17. = 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 &amp;&#39;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

CouCow具有相同的结构,因此您几乎可以从serde的实现中进行复制粘贴。

  1. use std::{sync::Arc};
  2. use std::borrow::Borrow;
  3. use std::ops::Deref;
  4. use serde::{Deserializer, Deserialize, Serializer, Serialize};
  5. pub enum Cou<'a, T>
  6. where
  7. T: ToOwned + ?Sized,
  8. {
  9. Borrowed(&'a T),
  10. Upgraded(Arc<T::Owned>),
  11. }
  12. impl<B: ?Sized + ToOwned> Deref for Cou<'_, B>
  13. where
  14. B::Owned: Borrow<B>,
  15. {
  16. type Target = B;
  17. fn deref(&self) -> &B {
  18. match *self {
  19. Cou::Borrowed(borrowed) => borrowed.borrow(),
  20. Cou::Upgraded(ref owned) => owned.deref().borrow(),
  21. }
  22. }
  23. }
  24. impl<'a, T: ?Sized> Serialize for Cou<'a, T> where T: Serialize + ToOwned {
  25. #[inline]
  26. fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
  27. where
  28. S: Serializer,
  29. {
  30. (**self).serialize(serializer)
  31. }
  32. }
  33. impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cou<'a, T>
  34. where
  35. T: ToOwned,
  36. T::Owned: Deserialize<'de>,
  37. {
  38. #[inline]
  39. fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  40. where
  41. D: Deserializer<'de>,
  42. {
  43. T::Owned::deserialize(deserializer).map(Arc::new).map(Cou::Upgraded)
  44. }
  45. }

Playground

英文:

Cou has the same structure as Cow, so you can almost copy-paste ser/de implementations from serde.

  1. use std::{sync::Arc};
  2. use std::borrow::Borrow;
  3. use std::ops::Deref;
  4. use serde::{Deserializer, Deserialize, Serializer, Serialize};
  5. pub enum Cou&lt;&#39;a, T&gt;
  6. where
  7. T: ToOwned + ?Sized,
  8. {
  9. Borrowed(&amp;&#39;a T),
  10. Upgraded(Arc&lt;T::Owned&gt;),
  11. }
  12. impl&lt;B: ?Sized + ToOwned&gt; Deref for Cou&lt;&#39;_, B&gt;
  13. where
  14. B::Owned: Borrow&lt;B&gt;,
  15. {
  16. type Target = B;
  17. fn deref(&amp;self) -&gt; &amp;B {
  18. match *self {
  19. Cou::Borrowed(borrowed) =&gt; borrowed.borrow(),
  20. Cou::Upgraded(ref owned) =&gt; owned.deref().borrow(),
  21. }
  22. }
  23. }
  24. impl &lt;&#39;a, T: ?Sized&gt; Serialize for Cou&lt;&#39;a, T&gt; where T: Serialize + ToOwned {
  25. #[inline]
  26. fn serialize&lt;S&gt;(&amp;self, serializer: S) -&gt; Result&lt;S::Ok, S::Error&gt;
  27. where
  28. S: Serializer,
  29. {
  30. (**self).serialize(serializer)
  31. }
  32. }
  33. impl&lt;&#39;de, &#39;a, T: ?Sized&gt; Deserialize&lt;&#39;de&gt; for Cou&lt;&#39;a, T&gt;
  34. where
  35. T: ToOwned,
  36. T::Owned: Deserialize&lt;&#39;de&gt;,
  37. {
  38. #[inline]
  39. fn deserialize&lt;D&gt;(deserializer: D) -&gt; Result&lt;Self, D::Error&gt;
  40. where
  41. D: Deserializer&lt;&#39;de&gt;,
  42. {
  43. T::Owned::deserialize(deserializer).map(Arc::new).map(Cou::Upgraded)
  44. }
  45. }

Playground

huangapple
  • 本文由 发表于 2023年5月13日 14:58:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76241465.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定