使用 serde 反序列化动态外部标记值?

Deserialise dynamic externally tagged values with serde?

我遇到了一些数据,我正试图将其转换为与 serde 一起使用的结构。它是一个嵌套字典,其中每个后续条目的键是数据片段的版本号。我无法思考如何将其转换为将读取这些版本的动态数量的 serde 结构。我附上了一个我想出的糟糕例子,但这绝对是错误的。

我不确定我可以使用哪些关键词来搜索这方面的信息。我在文档中找到的一件事是 externally tagged enums 但是我不太确定这对我有帮助。

{
    "v0001": {
        "id": "a"
        // ...
    },
    "v0002": {
        "id": "b"
        // ...
    }
    "v0003": {
        "id": "c"
        // ...
    }
    // ...
}
use serde::{Deserialize, Serialize};

#[derive(Debug, Default, Serialize, Deserialize)]
pub struct Data {
    pub v0001: Version,
    pub v0002: Version,
    pub v0003: Version,
    // ??!
}

#[derive(Debug, Default, Serialize, Deserialize)]
pub struct Version {
    id: String,
}

我最终要做的是加载 json,附加一个新版本并将其重写回 json。

任何 help/thoughts/feedback 都会很棒! :)

在@cdknight 建议使用 HashMap 之后,我意识到根数据类型不必是 struct。这是我想出的一个可行的解决方案。我改用了 BTreeMap,这样按键就会井井有条。

type Data = BTreeMap<String, Version>;

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

fn main() {
    let input = r#"
    {
        "v0001": {
            "id": "a"
        },
        "v0002": {
            "id": "b"
        },
        "v0003": {
            "id": "c"
        }
    }"#;

    let data: Data = serde_json::from_str(input).unwrap();
    dbg!(&data);

    let vec: Vec<Version> = data.into_values().collect();
    dbg!(&vec);
}

输出:

[src/main.rs:106] &data = {
    "v0001": Version {
        id: "a",
    },
    "v0002": Version {
        id: "b",
    },
    "v0003": Version {
        id: "c",
    },
}
[src/main.rs:109] &vec = [
    Version {
        id: "a",
    },
    Version {
        id: "b",
    },
    Version {
        id: "c",
    },
]