如何使用Serde从原始结构的JSON反序列化结构的子字段? [英] How to deserialize a subfield of a struct from the original struct's JSON with Serde?

查看:186
本文介绍了如何使用Serde从原始结构的JSON反序列化结构的子字段?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从Test对象本身的数据中反序列化Test::team_size属性:

I want to have the Test::team_size attribute be deserialized from the data of Test object itself:

#[derive(Debug, Serialize, Deserialize)]
struct TeamSize {
    pub min: i64,
    pub max: i64,
}

#[derive(Debug, Serialize, Deserialize)]
struct Test {
    pub i: i64,
    pub team_size: TeamSize,
}

fn main() {
    let t: Test = serde_json::from_str(r#"{"i": -2, "min": 2, "max": 5}"#).unwrap();
    assert_eq!(t.i, -2);
    assert_eq!(t.team_size.min, 2);
    assert_eq!(t.team_size.max, 5);
}

此代码无法编译,我不知道如何使Serde满足我的要求.在此示例中,是否有办法从作为子字段的原始结构的JSON反序列化team_size?

This code does not compile and I don't know how to make Serde do what I want. Is there a way to deserialize team_size in this example from the JSON of the original structure where it is a subfield?

似乎我想要类似的东西 #[serde(untagged)] 但是对于一个结构和一个字段,而不是整个结构.

It seems that I want something like #[serde(untagged)] but for a struct and for a field and not the whole struct.

推荐答案

从Serde 1.0.34开始,您现在可以使用

As of Serde 1.0.34, you can now use #[serde(flatten)]:

#[derive(Debug, Serialize, Deserialize)]
struct Test {
    pub i: i64,
    #[serde(flatten)]
    pub team_size: TeamSize,
}


在此之前,最简单的解决方法是将反序列化为私有帮助程序类型并根据需要对其进行重组:


Before this, the easiest workaround would be to deserialize into a private helper type and restructure it as needed:

#[macro_use]
extern crate serde_derive;

extern crate serde;
extern crate serde_json;

use serde::{Serialize, Serializer, Deserialize, Deserializer};

#[derive(Debug)]
pub struct TeamSize {
    pub min: i64,
    pub max: i64,
}

#[derive(Debug)]
pub struct Test {
    pub i: i64,
    pub team_size: TeamSize,
}

// Private helper
#[derive(Serialize, Deserialize)]
struct Helper {
    pub i: i64,
    pub min: i64,
    pub max: i64,
}

impl Serialize for Test {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        let helper = Helper {
            i: self.i,
            min: self.team_size.min,
            max: self.team_size.max,
        };
        helper.serialize(serializer)
    }
}

impl<'de> Deserialize<'de> for Test {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer<'de>
    {
        let helper = Helper::deserialize(deserializer)?;
        Ok(Test {
            i: helper.i,
            team_size: TeamSize {
                min: helper.min,
                max: helper.max,
            },
        })
    }
}

fn main() {
    let j = r#" { "i": -2, "min": 2, "max": 5 } "#;

    let de: Test = serde_json::from_str(j).unwrap();
    println!("{:#?}", de);

    let ser = serde_json::to_string_pretty(&de).unwrap();
    println!("{}", ser);
}

这篇关于如何使用Serde从原始结构的JSON反序列化结构的子字段?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆