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

编程入门 行业动态 更新时间:2024-10-13 10:25:52
本文介绍了使用Serde将两种类型转换为单一类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我正在写一个程序,该程序可以挂接到返回JSON的Web服务中.

I'm writing for a program that hooks into a web service which sends back JSON.

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

When a certain property isn't there it provides a empty object, with all its fields as empty strings instead of excluding the value. When the property exists, some of the properties are u64. How can I have it so Serde handles this case?

#[derive(Clone, Debug, Deserialize)] struct WebResponse { foo: Vec<Foo>, } #[derive(Clone, Debug, Deserialize)] struct Foo { points: Points, } #[derive(Clone, Debug, Deserialize)] struct Points { x: u64, y: u64, name: String, }

示例JSON

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

推荐答案

Serde支持选择属性 a>可用于自定义类型的序列化或反序列化,同时仍在很大程度上使用派生的实现.

Serde supports an interesting selection of attributes that can be used to customize the serialization or deserialization for a type while still using the derived implementation for the most part.

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

In your case, you need to be able to decode a field that can be specified as one of multiple types, and you don't need information from other fields to decide how to decode the problematic fields. The #[serde(deserialize_with="$path")] annotation is well suited to solve your problem.

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

We need to define a function that will decode either an empty string or an integer value into an u64. We can use the same function for both fields, since we need the same behavior. This function will use a custom Visitor to be able to handle both strings and integers. It's a bit long, but it makes you appreciate all the work that Serde is doing for you!

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, Debug, Deserialize)] struct WebResponse { foo: Vec<Foo>, } #[derive(Clone, Debug, Deserialize)] struct Foo { points: Points, } #[derive(Clone, Debug, Deserialize)] struct Points { #[serde(deserialize_with = "deserialize_u64_or_empty_string")] x: u64, #[serde(deserialize_with = "deserialize_u64_or_empty_string")] y: u64, name: String, } 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, E> where E: de::Error, { 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"

更多推荐

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

本文发布于:2023-11-06 08:20:29,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1563175.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:转换为   两种类型   类型   Serde

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!