如何将多个键值条目的 JSON 对象反序列化为 Rust 中的自定义结构

Posted

技术标签:

【中文标题】如何将多个键值条目的 JSON 对象反序列化为 Rust 中的自定义结构【英文标题】:How to deserialize JSON object of multiple key value entries to custom struct in Rust 【发布时间】:2022-01-12 02:13:47 【问题描述】:

我正在尝试将一组未知的键值样式标签从 JSON 反序列化到我的结构中。

这是我当前解析 JSON 的实现:

use std::collections::HashMap;
use serde::Serialize, Deserialize;
use anyhow::Result;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Node 
    metadata: Metadata,
    pub spec: Spec,


#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Metadata 
    name: String,
    labels: HashMap<String, String>,
    expires: String,
    id: i64,


#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Spec 
    pub hostname: String,


fn main() -> Result<()> 
    let json = r#"
[
  
    "metadata": 
      "name": "161bee39-cf07-4e31-90ba-6593c9f505cb",
      "labels": 
        "application": "api",
        "owner": "team_x"
      ,
      "expires": "2021-12-06T20:49:04.136656523Z",
      "id": 1638823144137190452
    ,
    "spec": 
      "hostname": "host1.example.com"
    
  ,
  
    "metadata": 
      "name": "c1b3ee09-8e4a-49d4-93b8-95cbcb676f20",
      "labels": 
        "application": "database",
        "owner": "team_y"
      ,
      "expires": "2021-12-06T20:49:55.23841272Z",
      "id": 1638823195247684748
    ,
    "spec": 
      "hostname": "host2.example.com"
    
  
]
    "#;
    let nodes: Vec<Node> = serde_json::from_str(json)?;
    println!(":?", nodes);
    Ok(())

该示例可以正常工作,但现在我想添加一个这样的 Label 结构:

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Metadata 
    name: String,
    labels: Vec<Label>,
    expires: String,
    id: i64,


#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Label 
    key: String,
    value: String,

这显然不起作用,但我不确定如何从这里继续。根据我在这个问题之前的研究,我知道您可以实现自定义反序列化器,但我不知道如何正确地做到这一点。也许这也不是最好的方法,我没有看到明显的解决方案。

提前感谢任何示例或帮助。

【问题讨论】:

我不明白,你为什么要那样做? 说实话,我可以继续使用 HashMap 方法,因为 Label 结构可能不是一个好方法,但现在我研究了很多关于如何做到这一点点我有点想知道如何做到这一点。 docs.rs/serde_with/1.11.0/serde_with/rust/tuple_list_as_map/… 非常感谢,这很有帮助! 【参考方案1】:

根据 Stargateurs 的评论,serde_with crate 提供了一个解决方案:

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Metadata 
    name: String,
    #[serde(with = "serde_with::rust::tuple_list_as_map")]
    labels: Vec<Label>,
    expires: String,
    id: i64,


type Label = (String, String);

【讨论】:

以上是关于如何将多个键值条目的 JSON 对象反序列化为 Rust 中的自定义结构的主要内容,如果未能解决你的问题,请参考以下文章

如何将 JSON 反序列化为具有多个 List<T> 参数的 .NET 对象?

将 JSON 字符串反序列化为多个 C# 对象

将json键值反序列化为字典c#

将 JSON 命名属性反序列化为 .Net 对象

如何在 C# 中反序列化多个 JSON 对象?

如何将对象的json数组反序列化为字典[重复]