代码之家  ›  专栏  ›  技术社区  ›  John Graham

是否获取serde_json来识别此枚举表示?

  •  1
  • John Graham  · 技术社区  · 2 年前

    我有JSON数据,可以用serde解析,基本上看起来是这样的(大大简化了!):

    {
        "id": 1,
        "object": "Type1",
        "data": {
            "type_1_name": "value_1"
        }
    }
    {
        "id": 2,
        "object": "Type2",
        "data": {
            "type_2_name": "value_2"
        }
    }
    

    下面是我用来解析的代码:

    #![allow(unused)]
    
    use serde::Deserialize;
    use serde_json::json;
    
    #[derive(Deserialize)]
    struct Item {
        id: u32,
        object: String,
    
        //#[serde(tag = "object")]
        data: Data,
    }
    
    #[derive(Deserialize)]
    #[serde(untagged)]
    //#[serde(tag = "object")]
    //#[serde(tag = "object", content = "data")]
    enum Data {
        Type1(Type1),
        Type2(Type2),
    }
    
    #[derive(Deserialize)]
    struct Type1 {
        type_1_name: String,
    }
    
    #[derive(Deserialize)]
    struct Type2 {
        type_2_name: String,
    }
    
    fn main() {
        let json = json!([
            {
                "id": 1,
                "object": "Type1",
                "data": {
                    "type_1_name": "value_1"
                }
            },
            {
                "id": 2,
                "object": "Type2",
                "data": {
                    "type_2_name": "value_2"
                }
            }
        ]);
    
        let _json: Vec<Item> = serde_json::from_value(json).unwrap();
    }
    

    另请参见 rust playground

    当我解析它时,我希望顶级数据结构是相同的类型( Data 在示例中),因为它们有公共字段,因此对它们进行迭代会很有用。

    我可以成功地获得serde来解析较低级别的值类型( Type1 / Type2 )如果我使用 #[serde(untagged)] 然而,在大型数据集上,如果错误只是“不匹配”,则很难找到错误-我有 object 告诉我什么类型的字段 data 领域 应该 是的,所以我希望我能告诉serde使用它来知道它应该是哪一个,但由于各种原因,我所做的尝试(在示例中注释掉了标签)都不起作用。

    有人知道如何告诉serde它知道数据的类型,但信息比它“高一级”吗?

    (另请参阅 the serde docs )

    1 回复  |  直到 2 年前
        1
  •  2
  •   Caesar    2 年前

    你差点就受够了:

    • 不要消费 object 字段在 Item
    • flatten data 进入 项目
    #[derive(Deserialize, Debug)]
    struct Item {
        id: u32,
        #[serde(flatten)]
        data: Data,
    }
    
    #[derive(Deserialize, Debug)]
    #[serde(tag = "object", content = "data")]
    enum Data {
        Type1(Type1),
        Type2(Type2),
    }
    

    Playground

    推荐文章