在序列化时添加一个额外的字段。

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

Add an additional field while serializing

问题

在Serde序列化中,如何添加一个额外的字段:

  1. #[derive(Serialize)]
  2. struct X {
  3. a: u32,
  4. b: u32,
  5. c: u32,
  6. }

我想要在JSON序列化中添加一个名为 d,值为 "qwe" 的字段。如何在不从头开始编写X的序列化器的情况下实现这一目标?

英文:

In Serde serializers, how to add an additional field:

  1. #[derive(Serialize)]
  2. struct X {
  3. a: u32,
  4. b: u32,
  5. c: u32,
  6. }

I want to add to JSON serialization field d with value "qwe". How without writing completely a serializer for X from scratch?

答案1

得分: 6

自定义的Serialize实现并不算太糟糕:

  1. use serde::ser::{Serialize, Serializer, SerializeStruct};
  2. struct X {
  3. a: u32,
  4. b: u32,
  5. c: u32,
  6. }
  7. impl Serialize for X {
  8. fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
  9. where
  10. S: Serializer,
  11. {
  12. let mut x = serializer.serialize_struct("X", 4)?;
  13. x.serialize_field("a", &self.a)?;
  14. x.serialize_field("b", &self.b)?;
  15. x.serialize_field("c", &self.c)?;
  16. x.serialize_field("d", "qwe")?;
  17. x.end()
  18. }
  19. }

如您所要求,这只是代码的翻译部分,没有其他内容。

英文:

A custom Serialize implementation isn't so bad:

  1. use serde::ser::{Serialize, Serializer, SerializeStruct};
  2. struct X {
  3. a: u32,
  4. b: u32,
  5. c: u32,
  6. }
  7. impl Serialize for X {
  8. fn serialize&lt;S&gt;(&amp;self, serializer: S) -&gt; Result&lt;S::Ok, S::Error&gt;
  9. where
  10. S: Serializer,
  11. {
  12. let mut x = serializer.serialize_struct(&quot;X&quot;, 4)?;
  13. x.serialize_field(&quot;a&quot;, &amp;self.a)?;
  14. x.serialize_field(&quot;b&quot;, &amp;self.b)?;
  15. x.serialize_field(&quot;c&quot;, &amp;self.c)?;
  16. x.serialize_field(&quot;d&quot;, &quot;qwe&quot;)?;
  17. x.end()
  18. }
  19. }

答案2

得分: 4

假设您不介意字段 d 的存在,但只是不希望它在您的结构体中占用空间,您可以将其大小设为零,并在序列化时使用 serialize_with 属性来生成所需的数据:

  1. #[derive(Serialize)]
  2. struct X {
  3. a: u32,
  4. b: u32,
  5. c: u32,
  6. #[serde(serialize_with = "emit_qwe")]
  7. d: (),
  8. }
  9. fn emit_qwe<S: Serializer>(_: &(), s: S) -> Result<S::Ok, S::Error> {
  10. s.serialize_str("qwe")
  11. }

Playground

英文:

Assuming that you don't mind that the field d exists, but you just don't want it taking space in your struct, you can make it zero-sized and use the serialize_with attribute to emit the desired data when serializing:

  1. #[derive(Serialize)]
  2. struct X {
  3. a: u32,
  4. b: u32,
  5. c: u32,
  6. #[serde(serialize_with = &quot;emit_qwe&quot;)]
  7. d: (),
  8. }
  9. fn emit_qwe&lt;S: Serializer&gt;(_: &amp;(), s: S) -&gt; Result&lt;S::Ok, S::Error&gt; {
  10. s.serialize_str(&quot;qwe&quot;)
  11. }

Playground

答案3

得分: 3

你可以创建一个单独的结构体,它使用 #[derive(Serialize)] 并将你的结构体的所有内容复制过去

  1. impl Serialize for X {
  2. fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
  3. #[derive(Serialize)]
  4. struct XSerialize {
  5. a: u32,
  6. b: u32,
  7. c: u32,
  8. d: &'static str,
  9. }
  10. XSerialize {
  11. a: self.a,
  12. b: self.b,
  13. c: self.c,
  14. d: "only at serialization"
  15. }.serialize(serializer)
  16. }
  17. }

这样可以让你按照注释中指定的方式计算 d 的值。

英文:

You can create a separate struct that's #[derive(Serialize)] and copy everything in your struct over

  1. impl Serialize for X {
  2. fn serialize&lt;S: serde::Serializer&gt;(&amp;self, serializer: S) -&gt; Result&lt;S::Ok, S::Error&gt; {
  3. #[derive(Serialize)]
  4. struct XSerialize {
  5. a: u32,
  6. b: u32,
  7. c: u32,
  8. d: &amp;&#39;static str,
  9. }
  10. XSerialize {
  11. a: self.a,
  12. b: self.b,
  13. c: self.c,
  14. d: &quot;only at serialization&quot;
  15. }.serialize(serializer)
  16. }
  17. }

This should allow you to compute a value for d as you specify in the comments.

huangapple
  • 本文由 发表于 2023年2月24日 03:36:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/75549538.html
匿名

发表评论

匿名网友

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

确定