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

Rust中serde_json序列化枚举为何输出格式不一致?

为什么IpAddr序列化为JSON字符串,自定义枚举却输出JSON对象?

这两种输出差异的核心原因是序列化逻辑的实现方式不同:

1. std::net::IpAddr的序列化逻辑

IpAddr是Rust标准库类型,serde为它提供了定制化的Serialize实现——直接将IP地址转换成对应的字符串表示,因此序列化后输出的是JSON字符串类型。

你的示例代码及输出:

use std::net::IpAddr;

fn main() {
    let addr : IpAddr = "127.0.0.1".parse().unwrap();
    let json = serde_json::to_string(&addr).unwrap();
    println!("{}", json);
}

输出:

"127.0.0.1"

2. 自定义枚举的默认序列化行为

当你给自定义枚举添加#[derive(Serialize)]时,serde会使用默认的枚举序列化规则:对于带单个字段的变体,默认采用「外部标签(external tagging)」格式——将变体名称作为JSON对象的键,变体的字段值作为对应的值,因此输出是JSON对象。

你的自定义枚举示例代码及输出:

use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
enum Foo {
    One(String),
    Two(String),
}

fn main() {
    let foo = Foo::One("one".to_string());
    let json = serde_json::to_string(&foo).unwrap();
    println!("{}", json);
}

输出:

{"One":"one"}

让自定义枚举输出JSON字符串的方法

如果想让自定义枚举和IpAddr一样输出JSON字符串,可以通过两种方式实现:

方式一:使用serde属性修改行为

如果枚举的所有变体都只包含String类型字段,可以用#[serde(into = "String")]统一转换为字符串:

use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
#[serde(into = "String")]
enum Foo {
    One(String),
    Two(String),
}

// 需要实现从Foo到String的转换
impl From<Foo> for String {
    fn from(foo: Foo) -> Self {
        match foo {
            Foo::One(s) => s,
            Foo::Two(s) => s,
        }
    }
}

fn main() {
    let foo = Foo::One("one".to_string());
    let json = serde_json::to_string(&foo).unwrap();
    println!("{}", json); // 输出:"one"
}

方式二:手动实现Serialize trait

直接为枚举编写定制化的序列化逻辑,和IpAddr的实现思路一致:

use serde::{Serialize, Serializer};

enum Foo {
    One(String),
    Two(String),
}

impl Serialize for Foo {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        // 匹配不同变体,直接序列化内部的字符串
        match self {
            Foo::One(s) => serializer.serialize_str(s),
            Foo::Two(s) => serializer.serialize_str(s),
        }
    }
}

fn main() {
    let foo = Foo::One("one".to_string());
    let json = serde_json::to_string(&foo).unwrap();
    println!("{}", json); // 输出:"one"
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 16:25:23