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

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

Add an additional field while serializing

问题

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

#[derive(Serialize)]
struct X {
  a: u32,
  b: u32,
  c: u32,
}

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

英文:

In Serde serializers, how to add an additional field:

#[derive(Serialize)]
struct X {
  a: u32,
  b: u32,
  c: u32,
}

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实现并不算太糟糕:

use serde::ser::{Serialize, Serializer, SerializeStruct};

struct X {
  a: u32,
  b: u32,
  c: u32,
}

impl Serialize for X {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut x = serializer.serialize_struct("X", 4)?;
        x.serialize_field("a", &self.a)?;
        x.serialize_field("b", &self.b)?;
        x.serialize_field("c", &self.c)?;
        x.serialize_field("d", "qwe")?;
        x.end()
    }
}

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

英文:

A custom Serialize implementation isn't so bad:

use serde::ser::{Serialize, Serializer, SerializeStruct};

struct X {
  a: u32,
  b: u32,
  c: u32,
}

impl Serialize for X {
    fn serialize&lt;S&gt;(&amp;self, serializer: S) -&gt; Result&lt;S::Ok, S::Error&gt;
    where
        S: Serializer,
    {
        let mut x = serializer.serialize_struct(&quot;X&quot;, 4)?;
        x.serialize_field(&quot;a&quot;, &amp;self.a)?;
        x.serialize_field(&quot;b&quot;, &amp;self.b)?;
        x.serialize_field(&quot;c&quot;, &amp;self.c)?;
        x.serialize_field(&quot;d&quot;, &quot;qwe&quot;)?;
        x.end()
    }
}

答案2

得分: 4

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

#[derive(Serialize)]
struct X {
  a: u32,
  b: u32,
  c: u32,
  #[serde(serialize_with = "emit_qwe")]
  d: (),
}

fn emit_qwe<S: Serializer>(_: &(), s: S) -> Result<S::Ok, S::Error> {
    s.serialize_str("qwe")
}

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:

#[derive(Serialize)]
struct X {
  a: u32,
  b: u32,
  c: u32,
  #[serde(serialize_with = &quot;emit_qwe&quot;)]
  d: (),
}

fn emit_qwe&lt;S: Serializer&gt;(_: &amp;(), s: S) -&gt; Result&lt;S::Ok, S::Error&gt; {
    s.serialize_str(&quot;qwe&quot;)
}

Playground

答案3

得分: 3

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

impl Serialize for X {
    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        #[derive(Serialize)]
        struct XSerialize {
            a: u32,
            b: u32,
            c: u32,
            d: &'static str,
        }
        
        XSerialize {
            a: self.a,
            b: self.b,
            c: self.c,
            d: "only at serialization"
        }.serialize(serializer)
    }
}

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

英文:

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

impl Serialize for X {
    fn serialize&lt;S: serde::Serializer&gt;(&amp;self, serializer: S) -&gt; Result&lt;S::Ok, S::Error&gt; {
        #[derive(Serialize)]
        struct XSerialize {
            a: u32,
            b: u32,
            c: u32,
            d: &amp;&#39;static str,
        }
        
        XSerialize {
            a: self.a,
            b: self.b,
            c: self.c,
            d: &quot;only at serialization&quot;
        }.serialize(serializer)
    }
}

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:

确定