如何反序列化具有重复键的 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
}
]
...
我的 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
}
结构 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,
},
],
),
}
我正在尝试反序列化一些具有重复键的 JSON,它们可能有任意数量。 JSON 看起来像这样:
...
"abilities": [
{
"ability_id": 5134,
"ability_level": 3
},
{
"ability_id": 5136,
"ability_level": 3
}
],
"abilities": [
{
"ability_id": 7710,
"ability_level": 4
}
]
...
我的 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
}
结构 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,
},
],
),
}