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

Rust Serde自定义序列化:String转&'static str及动态键名需求

如何用Serde实现动态键的自定义序列化

我需要将如下定义的Data结构体序列化为以key字段值为键、value字段值为值的JSON对象,而不是默认的包含key和value两个固定字段的结构。

原代码:

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

struct Data {
    key: String,    // 或 &str
    value: i32,
}

impl Serialize for Data {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut state = serializer.serialize_struct("Data", 1)?;

        // 尝试用动态key但出现生命周期错误
        // let key = (&self.key).to_string();
        // state.serialize_field(&*key, &self.value)?;
      
        state.serialize_field("key", &self.value)?;
        state.end()
    }
}

fn main() {
    let data = Data {
        key: String::from("age"),
        value: 21,
    };

    let json = serde_json::to_string_pretty(&data).unwrap();

    println!("the JSON is: {}", json)
}

默认序列化结果:

{
  "key": "age",
  "value": 21
}

期望的序列化结果:

{
  "age": 21
}

核心思路

Serde的serialize_struct适用于编译期固定字段名的结构体序列化,而动态键值对的场景应该使用serialize_map方法——因为JSON对象本质是键值对映射,而非固定字段的结构体。

针对String类型key的实现

use serde::{Serialize, Serializer};
use serde_json;

struct Data {
    key: String,
    value: i32,
}

impl Serialize for Data {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        // 创建包含1个键值对的map序列化状态
        let mut map = serializer.serialize_map(Some(1))?;
        // 插入动态键与对应的值
        map.serialize_entry(&self.key, &self.value)?;
        map.end()
    }
}

fn main() {
    let data = Data {
        key: String::from("age"),
        value: 21,
    };

    let json = serde_json::to_string_pretty(&data).unwrap();
    println!("{}", json);
}

针对&str类型key的实现(含生命周期)

如果Data的key是引用类型,需要正确标注生命周期以避免错误:

use serde::{Serialize, Serializer};
use serde_json;

struct Data<'a> {
    key: &'a str,
    value: i32,
}

impl<'a> Serialize for Data<'a> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut map = serializer.serialize_map(Some(1))?;
        map.serialize_entry(self.key, &self.value)?;
        map.end()
    }
}

fn main() {
    let data = Data {
        key: "age",
        value: 21,
    };

    let json = serde_json::to_string_pretty(&data).unwrap();
    println!("{}", json);
}

原代码报错原因

原代码尝试用serialize_struct传入动态生成的String作为字段名时,serialize_field要求字段名的生命周期至少覆盖序列化器的整个操作周期。但临时创建的String会在当前作用域结束后被释放,无法满足生命周期要求。而serialize_map的serialize_entry方法对键的生命周期要求更灵活,只要键在序列化过程中有效即可,完美适配动态生成的键场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 18:50:27