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

如何使用Serde反序列化嵌套结构体形式的JSON与YAML数据?

问题分析与解决方案

你的初始代码无法反序列化的核心原因是:JSON/YAML中scjson数组的每个元素并不是直接的StateMachine对象,而是一个以"StateMachine"为键、包裹着StateMachine实例的对象。同时,最终YAML里的各类状态(AtomicState、ParallelState等)属于标签式的多态结构,需要用枚举来处理。

1. 基础JSON反序列化修正

针对你给出的JSON结构,需要先定义一个包裹结构体来匹配"StateMachine"键:

use serde::{Deserialize, Serialize};

#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
pub struct StateMachine {
    id: String,
}

// 用于匹配数组中每个{"StateMachine": ...}的结构
#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
pub struct StateMachineEntry {
    #[serde(rename = "StateMachine")]
    state_machine: StateMachine,
}

#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
pub struct Scjson {
    scjson: Vec<StateMachineEntry>,
}

// 反序列化示例
fn main() -> Result<(), serde_json::Error> {
    let json = r#"{
        "scjson": [
            { "StateMachine": { "id": "sm_1" } },
            { "StateMachine": { "id": "sm_2" } }
        ]
    }"#;
    
    let data: Scjson = serde_json::from_str(json)?;
    println!("{:?}", data);
    Ok(())
}

2. 最终YAML完整解析方案

针对包含多态状态的YAML,需要用枚举来处理不同类型的状态(AtomicState、FinalState等),同时匹配各类嵌套结构:

use serde::{Deserialize, Serialize};
use serde_yaml;

// 定义各类状态的结构体
#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
pub struct AtomicState {
    id: String,
    #[serde(default)] // 处理可选的transitions字段
    transitions: Vec<TransitionEntry>,
}

#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
pub struct ParallelState {
    #[serde(rename = "InitialTransition")]
    initial_transition: InitialTransition,
}

#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
pub struct CompoundState {
    id: String,
    #[serde(rename = "initialTransition")]
    initial_transition: Transition,
}

#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
pub struct FinalState {
    id: String,
    #[serde(rename = "onEntry")]
    on_entry: String,
}

// 定义Transition相关结构
#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
pub struct Transition {
    event: String,
    #[serde(rename = "executable_content")]
    executable_content: String,
}

#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
pub struct TransitionEntry {
    #[serde(rename = "Transition")]
    transition: Transition,
}

#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
pub struct InitialTransition {
    // 空对象,无需字段
}

// 用枚举统一所有状态类型
#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
#[serde(rename_all = "PascalCase")]
pub enum State {
    AtomicState(AtomicState),
    ParallelState(ParallelState),
    CompoundState(CompoundState),
    FinalState(FinalState),
}

// 更新StateMachine结构体,添加states字段
#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
pub struct StateMachine {
    id: String,
    states: Vec<State>,
}

// 包裹StateMachine的结构体
#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
pub struct StateMachineEntry {
    #[serde(rename = "StateMachine")]
    state_machine: StateMachine,
}

// 顶层结构体
#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
pub struct Scjson {
    scjson: Vec<StateMachineEntry>,
}

// YAML反序列化示例
fn main() -> Result<(), serde_yaml::Error> {
    let yaml = r#"scjson:
  - StateMachine:
      id: "sm_1"
      states:
        - AtomicState:
            id: atomic_1
        - AtomicState:
            id: atomic_2
            transitions:
              - Transition: { event: "E1", executable_content: "asdf" }
        - ParallelState:
            InitialTransition: { }
        - CompoundState:
            id: compound_1
            initialTransition: { event: "E2", condition: "some condition" }
  - StateMachine:
      id: "sm_2"
      states:
        - FinalState:
            id: "asdf"
            onEntry: "17"
"#;
    
    let data: Scjson = serde_yaml::from_str(yaml)?;
    println!("{:?}", data);
    Ok(())
}

关键说明

  • 对于{"TypeName": {...}}这种标签式结构,使用枚举+#[serde(rename_all = "PascalCase")]可以让serde自动将键名匹配到枚举变体。
  • 字段命名不匹配时(比如YAML中的initialTransition、onEntry),用#[serde(rename = "...")]手动映射。
  • 可选字段(如AtomicState的transitions)添加#[serde(default)]来处理缺失情况,默认生成空数组/默认值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 22:25:22