json – 使用Serde将两种类型转换为单一类型

前端之家收集整理的这篇文章主要介绍了json – 使用Serde将两种类型转换为单一类型前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在编写一个程序,它挂钩到一个发回 JSON的Web服务.

当某个属性不存在时,它提供一个空对象,其所有字段为空字符串,而不是排除该值.当属性存在时,一些属性是u64.我怎么能拥有它以便Serde处理这个案子?

Rust Structs

#[derive(Clone,Debug,Deserialize)]
struct WebResponse {
    foo: Vec<Foo>,}

#[derive(Clone,Deserialize)]
struct Foo {
    points: Points,Deserialize)]
struct Points {
    x: u64,y: u64,name: String,}

示例JSON

{
    "foo":[
        {
            "points":{
                "x":"","y":"","name":""
            }
        },{
            "points":{
                "x":78,"y":92,"name":"bar"
            }
        }
    ]
}

解决方法

Serde支持一个有趣的 attributes选择,可用于自定义类型的序列化或反序列化,同时仍然大部分使用派生实现.

在您的情况下,您需要能够解码可以指定为多种类型之一的字段,并且您不需要来自其他字段的信息来决定如何解码有问题的字段. #[serde(deserialize_with =“$path”)]注释非常适合解决您的问题.

我们需要定义一个函数,将空字符串或整数值解码为u64.我们可以对两个字段使用相同的函数,因为我们需要相同的行为.此函数将使用自定义Visitor来处理字符串和整数.它有点长,但它让你欣赏Serde为你做的所有工作!

extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

use serde::Deserializer;
use serde::de::{self,Unexpected};
use std::fmt;

#[derive(Clone,Deserialize)]
struct Points {
    #[serde(deserialize_with = "deserialize_u64_or_empty_string")]
    x: u64,#[serde(deserialize_with = "deserialize_u64_or_empty_string")]
    y: u64,}

struct DeserializeU64OrEmptyStringVisitor;

impl<'de> de::Visitor<'de> for DeserializeU64OrEmptyStringVisitor {
    type Value = u64;

    fn expecting(&self,formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("an integer or a string")
    }

    fn visit_u64<E>(self,v: u64) -> Result<Self::Value,E>
    where
        E: de::Error,{
        Ok(v)
    }

    fn visit_str<E>(self,v: &str) -> Result<Self::Value,{
        if v == "" {
            Ok(0)
        } else {
            Err(E::invalid_value(Unexpected::Str(v),&self))
        }
    }
}

fn deserialize_u64_or_empty_string<'de,D>(deserializer: D) -> Result<u64,D::Error>
where
    D: Deserializer<'de>,{
    deserializer.deserialize_any(DeserializeU64OrEmptyStringVisitor)
}

fn main() {
    let value = serde_json::from_str::<WebResponse>(
        r#"{
        "foo": [
            {
                "points": {
                    "x": "","y": "","name": ""
                }
            },{
                "points": {
                    "x": 78,"y": 92,"name": "bar"
                }
            }
        ]
    }"#,);
    println!("{:?}",value);
}

Cargo.toml:

[dependencies]
serde = "1.0.15"
serde_json = "1.0.4"
serde_derive = "1.0.15"

猜你在找的JavaScript相关文章