You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Serde反序列化含字符串或字符串数组字段的JSON数据?

使用Serde反序列化支持字符串/字符串数组的JSON数据

你的JSON数据中,字段既可以是单个字符串,也可以是字符串数组,这种场景下可以通过两种方式实现Serde反序列化:

方法一:使用serde_with库的OneOrMany类型(推荐)

serde_with库提供了现成的OneOrMany类型,专门处理这种"单个值或数组"的情况,无需手动编写反序列化逻辑。

步骤1:添加依赖

在Cargo.toml中加入对应依赖:

[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_with = "3.0"

步骤2:定义结构体

使用#[serde_as]属性标记结构体,字段类型指定为OneOrMany<String>,最终会统一解析为Vec<String>:

use serde::Deserialize;
use serde_with::{serde_as, OneOrMany};

#[serde_as]
#[derive(Debug, Deserialize)]
struct MyData {
    #[serde_as(as = "OneOrMany<_>")]
    keya: Vec<String>,
    #[serde_as(as = "OneOrMany<_>")]
    keyb: Vec<String>,
}

步骤3:反序列化示例

fn main() -> Result<(), serde_json::Error> {
    // 测试单个字符串的情况
    let json1 = r#"{
        "keya": "some string",
        "keyb": "some string"
    }"#;
    let data1: MyData = serde_json::from_str(json1)?;
    println!("{:?}", data1); // MyData { keya: ["some string"], keyb: ["some string"] }

    // 测试混合类型的情况
    let json2 = r#"{
        "keya": "some string",
        "keyb": ["some string", "some string"]
    }"#;
    let data2: MyData = serde_json::from_str(json2)?;
    println!("{:?}", data2); // MyData { keya: ["some string"], keyb: ["some string", "some string"] }

    // 另外两种数组+字符串、数组+数组的格式也可正常解析
    Ok(())
}

方法二:自定义反序列化类型(不依赖额外库)

如果不想引入第三方库,可以手动实现支持两种类型的自定义结构体,并实现Deserialize trait。

步骤1:定义自定义类型与反序列化逻辑

use serde::de::{self, Deserializer, Visitor};
use serde::Deserialize;
use std::fmt;

#[derive(Debug)]
struct StringOrArray(Vec<String>);

struct StringOrArrayVisitor;

impl<'de> Visitor<'de> for StringOrArrayVisitor {
    type Value = StringOrArray;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("a string or an array of strings")
    }

    // 处理单个字符串
    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        Ok(StringOrArray(vec![v.to_string()]))
    }

    // 处理字符串数组
    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
    where
        A: de::SeqAccess<'de>,
    {
        let mut vec = Vec::new();
        while let Some(s) = seq.next_element()? {
            vec.push(s);
        }
        Ok(StringOrArray(vec))
    }
}

impl<'de> Deserialize<'de> for StringOrArray {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_any(StringOrArrayVisitor)
    }
}

步骤2:在主结构体中使用

#[derive(Debug, Deserialize)]
struct MyData {
    keya: StringOrArray,
    keyb: StringOrArray,
}

使用时可通过keya.0访问内部的Vec<String>集合。

步骤3:测试反序列化

逻辑和方法一一致,四种JSON格式均可正常解析。


内容的提问来源于stack exchange,提问作者Happy Machine

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 06:01:36