将JSON数组反序列化为元组并给其类型标签

3

我有一个类似于以下结构的JSON:

[{"range": [1, 2]}, {"range": [2, 5]}]

数组中的对象除了range字段以外还有其他字段,但这并不重要。

是否可能自动将它们反序列化为带有两个幻像类型的元组,以指示起始和结束是否包含?

这也可以通过将数字反序列化为带有幻像类型的某种元组来解决。

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

use std::marker::PhantomData;

#[derive(Debug)]
struct Inclusive;
#[derive(Debug)]
struct Exclusive;

#[derive(Deserialize)]
struct Range<S, E, V: Ord>(Option<V>, Option<V>, PhantomData<S>, PhantomData<E>);

fn main() {
    let data = "[1, 2]";
    let r: Range<Inclusive, Exclusive, i32> = serde_json::from_str(data).expect("Error");
    println!("Range from {:?} to {:?}", r.0, r.1);
}

这不起作用是因为serde_json似乎对PhantomData一无所知,并且期望大小为4的数组,可以通过手动实现Deserializer来解决这个问题,而我想要避免这种情况发生。
我并不抱太大希望,但也许有什么我不知道的方法。
1个回答

3
你似乎希望serde完全忽略某些字段。可以使用#[serde(skip)]。Serde会从Default::default()中获取默认值,这适用于PhantomData
#[derive(Debug, Deserialize)]
struct Range<S, E, V: Ord>(
    Option<V>,
    Option<V>,
    #[serde(skip)] PhantomData<S>,
    #[serde(skip)] PhantomData<E>,
);

游乐场

顺便提一下,如果你的类型InclusiveExclusive总是类似单元的而不是单例的,那么你可以考虑直接持有它们,而不是使用PhantomData,因为它们也是零大小的。

#[derive(Debug, Default)]
struct Inclusive;
#[derive(Debug, Default)]
struct Exclusive;

#[derive(Deserialize)]
struct Range<S, E, V: Ord>(
    Option<V>,
    Option<V>,
    #[serde(skip)] S,
    #[serde(skip)] E,
);

哦,谢谢!看起来是个不错的解决方案。有没有办法约束“Range”构造函数,使得边界值中只有一个是“Some”? - user1685095
@user1685095 我认为这应该作为一个独立的问题来提出。考虑使用枚举类型。 - E net4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接