如何反序列化具有重复键的 JSON 而不会丢失任何值?

How can I deserialize JSON that has duplicate keys without losing any of the values?

我正在尝试反序列化一些具有重复键的 JSON,它们可能有任意数量。 JSON 看起来像这样:

...
"abilities": [
    {
        "ability_id": 5134,
        "ability_level": 3
    }, 
    {
        "ability_id": 5136,
        "ability_level": 3
    }
],
"abilities": [
    {
        "ability_id": 7710,
        "ability_level": 4
    }
]
...

original json

我的 Rust 代码是:

#[derive(Deserialize, Debug)]
pub struct Ancient {
    score: usize,
    tower_state: usize,
    barracks_state: usize,
    picks: Option<Vec<HeroId>>,
    bans: Option<Vec<HeroId>>,
    players: Vec<PlayerDetailed>,
    abilities: Option<Vec<Ability>> // has many keys
}

original rust

结构 Ancient 是 json.

中另一个结构的一部分

只有最后一个 abilities 有很多键,而且数量不定,我读过 this 但无法将其更改为我喜欢的(我希望最终用户仍然有一个结构)。我什至尝试过 #[serde(flatten)],但它只是让一切变得 None。如果可能我也想改变它:

#[derive(Deserialize, Debug)]
pub struct Ancient {
    score: usize,
    tower_state: usize,
    barracks_state: usize,
    picks: Option<Vec<HeroId>>,
    bans: Option<Vec<HeroId>>,
    players: Vec<PlayerDetailed>,
    abilities_list: Option<abilities<Option<Vec<Ability>>>> 
}

JSON 规范并未明确禁止重复键,但大多数实现会忽略其中一个键以外的所有键。对于派生的 serde::Deserialize 实现,任何 serde 反序列化器,包括 serde_json,如果存在重复的键,都会出现恐慌。

如果您无法更改 json 格式,您可以为其中一种类型手动实施 Deserialize

让我们简化您的结构并 Json 一点。

JSON:

{
    "name": "sn99",
    "abilities": [
        {
            "ability_id": 5134,
            "ability_level": 3
        }, 
        {
            "ability_id": 5136,
            "ability_level": 3
        }
    ],
    "abilities": [
        {
            "ability_id": 7710,
            "ability_level": 4
        }
    ]
}

并解析成这样的结构:

use serde::Deserialize;

#[derive(Debug, Deserialize)]
struct Ability {
    ability_level: u32,
    ability_id: u32,
}

#[derive(Debug)]
struct Abilities(Vec<Ability>);

#[derive(Debug, Deserialize)]
struct Entity {
    name: String,
    #[serde(flatten)]
    abilities: Abilities,
}

注意Abilities不推导出Deserialize;我们将手动实施它:

use serde::de::{self, MapAccess, Visitor, Error as _};

impl<'de> Deserialize<'de> for Abilities {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: de::Deserializer<'de>,
    {
        struct MyVisitor;

        impl<'d> Visitor<'d> for MyVisitor {
            type Value = Vec<Ability>;

            fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
                f.write_str("a map of abilities")
            }

            fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
            where
                M: MapAccess<'d>,
            {
                let mut abilities = Vec::new();
                while let Some((key, mut value)) = access.next_entry()? {
                    if key == "abilities" {
                        abilities.append(&mut value);
                    } else {
                        return Err(M::Error::unknown_field(key, &["abilities"]));
                    }
                }
                Ok(abilities)
            }
        }
        Ok(Abilities(deserializer.deserialize_map(MyVisitor)?))
    }
}
let entity: Entity = serde_json::from_str(input).unwrap();
println!("{:#?}", entity);

产生:

Entity {
    name: "sn99",
    abilities: Abilities(
        [
            Ability {
                ability_level: 3,
                ability_id: 5134,
            },
            Ability {
                ability_level: 3,
                ability_id: 5136,
            },
            Ability {
                ability_level: 4,
                ability_id: 7710,
            },
        ],
    ),
}