将JSON数组反序列化为元组并为其指定类型标记

时间:2017-09-28 12:35:26

标签: rust serde phantom-types serde-json

我的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 个答案:

答案 0 :(得分: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>,
);

Playground

在(可能)侧面注释,如果您的类型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,
);