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

使用Serde展平Rust结构体遇挫:#[serde(flatten)]未按预期工作

解决Serde flatten用法误解及结构体展平问题

问题原因

你遇到的panic不是Serde的bug,是对#[serde(flatten)]的用法理解有误。这个属性的作用是将结构体的字段直接平级展开到父对象中,而非读取JSON里嵌套在某个键下的内容。

当你给Library里的artifact字段加flatten时,Serde会期望JSON里的每个library元素是直接包含path和url的对象:

{
  "path": "somepath",
  "url": "someurl"
}

但你的实际JSON里,path和url嵌套在artifact键下,Serde找不到直接的path字段,因此触发panic。

解决方案

根据你的需求——保留现有JSON结构,同时让Library结构体直接拥有path和url字段(无嵌套),以下是几种可行实现方式:

方式一:合并结构体+自定义反序列化

直接把Artifact的字段合并到Library,通过自定义反序列化逻辑从JSON的artifact键读取数据:

use serde::{Deserialize, Deserializer};
use serde_json::Result;

#[derive(Serialize, Deserialize, Debug)]
struct App {
    version: String,
    build_date: String,
    libraries: Vec<Library>
}

#[derive(Serialize, Debug)]
struct Library {
    path: String,
    url: String
}

#[derive(Deserialize)]
struct Artifact {
    path: String,
    url: String
}

impl<'de> Deserialize<'de> for Library {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let artifact = Artifact::deserialize(deserializer)?;
        Ok(Library {
            path: artifact.path,
            url: artifact.url,
        })
    }
}

方式二:使用字段重命名快速实现

如果不想编写自定义反序列化逻辑,可以直接用#[serde(rename)]指定JSON字段路径:

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug)]
struct App {
    version: String,
    build_date: String,
    libraries: Vec<Library>
}

#[derive(Serialize, Deserialize, Debug)]
struct Library {
    #[serde(rename = "artifact.path")]
    path: String,
    #[serde(rename = "artifact.url")]
    url: String
}

方式三:修改JSON结构适配原有代码

如果你能调整JSON格式,去掉libraries里的artifact嵌套,那么你原来的flatten用法就会生效:
修改后的JSON:

{
  "version": "0.2a",
  "build_date": "2023/12/12",
  "libraries": [
     {
       "path": "somepath",
       "url": "someurl"
     },
     {
       "path": "somepath",
       "url": "someurl"
     }
   ]
}

对应的结构体(和你最初的代码一致):

#[derive(Serialize, Deserialize, Debug)]
struct Library {
    #[serde(flatten)]
    artifact: Artifact
}

此时Library会通过flatten直接拥有path和url字段。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 20:38:29