rust 如何将JSON中的选项序列化为数组

sqxo8psd  于 2023-02-04  发布在  其他
关注(0)|答案(1)|浏览(134)

我正在一个相对较大的代码库中工作,其中的选项在JSON中表示为数组,因此None在JSON中表示为[]Some(thing)在JSON中表示为[thing]。(是的,如果您想知道,该代码库还包含Haskell。)如何覆盖默认的serde_json行为(即省略可选字段)以匹配这一点?
例如,结构体:

SomeData {
  foo: Some(1),
  bar: None
}

应序列化为JSON,如下所示:

{
  "foo": [1],
  "bar": []
}

当然,理论上可以为与代码库交互的每个结构体中的每个可选字段实现自定义序列化,但即使这是可能的,这也是一项艰巨的任务。
serde_json序列化some和none中似乎没有任何选项,所以我想这个解决方案将创建一个新的序列化器,继承serde_json中除了Option序列化和反序列化之外的几乎所有东西。有这样做的项目的例子吗?也可以创建一个fork,但是维护fork从来都不是很有趣。

qjp7pelc

qjp7pelc1#

当然,理论上可以为与代码库交互的每个结构体中的每个可选字段实现自定义序列化
没有必要为 * 每个字段 * 定制实现,通过使用serialize_with,您只需要一个转换函数,将任何可序列化的Option<T>的序列化描述为一个序列。

fn serialize_option_as_array<T, S>(value: &Option<T>, serializer: S) -> Result<S::Ok, S::Error>
where
    T: Serialize,
    S: Serializer,
{
    let len = if value.is_some() { 1 } else { 0 };
    let mut seq = serializer.serialize_seq(Some(len))?;
    for element in value {
        seq.serialize_element(element)?;
    }
    seq.end()
}

在结构体中使用它:

use serde_derive::Serialize;
use serde::ser::{Serialize, Serializer, SerializeSeq};
use serde_json;

#[derive(Debug, Serialize)]
struct SomeData {
    #[serde(serialize_with = "serialize_option_as_array")]
    foo: Option<i32>,
    #[serde(serialize_with = "serialize_option_as_array")]
    bar: Option<u32>,
}

let data = SomeData {
    foo: Some(5),
    bar: None,
};

println!("{}", serde_json::to_string(&data)?);

输出:

{"foo":[5],"bar":[]}

Playground
另见:

相关问题