有没有办法用 Serde 定义标签字段? [英] Is there a way to define a tag field with Serde?

查看:65
本文介绍了有没有办法用 Serde 定义标签字段?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要这样的东西:

#[derive(Debug, Serialize, Deserialize)]结构我的结构{字段 1:字符串,field2:选项,#[serde(tag(value = "tag_value"))]标签: ()}

#[serde(tag(value = "tag_value"))] 并不是真正的 Serde 提供的属性,它在这里只是为了表达一个想法.我知道我可以自己完成所有的序列化,使用远程,(de)serialize_with 等,但这些需要大量样板代码.>

想法是必须存在一个标签字段,MyStruct序列化为JSON应该是:

<代码>{"field1": "foo",字段2":42,标签":标签值"}

如果缺少tag"字段或映射到与tag_value"不同的值,反序列化必须失败.

解决方案

使用单个变体枚举:

使用serde;//1.0.104使用 serde_json;//1.0.48#[派生(调试,serde::序列化,serde::反序列化)]#[serde(rename_all = "snake_case")]枚举标签{标签值,}#[派生(调试,serde::序列化,serde::反序列化)]结构我的结构{字段 1:字符串,field2:选项,标签: 标签,}fn 主(){让 s = MyStruct {field1: "foo".to_string(),field2:一些(42),标签:标签::标签值,};//序列化时包含标签println!("{:?}", serde_json::to_string(&s));//反序列化时需要标记打印!("{:?}",serde_json::from_str::("{\"field1\":\"foo\",\"field2\":42,\"tag\":\"tag_value\"}"));打印!("{:?}",serde_json::from_str::("{\"field1\":\"foo\",\"field2\":42}"));//一个错误的标签失败打印!("{:?}",serde_json::from_str::<MyStruct>("{\"field1\":\"foo\",\"field2\":42,\"tag\":\"oops\"}"));}

打印出来

Ok("{\"field1\":\"foo\",\"field2\":42,\"tag\":\"tag_value\"}")Ok(MyStruct { field1: "foo", field2: Some(42), tag: TagValue })错误(错误(缺少字段`标签`",行:1,列:28))错误(错误(未知变体`oops`,预期`tag_value`",行:1,列:40))

(永久链接到游乐场)

I want something like this:

#[derive(Debug, Serialize, Deserialize)]
struct MyStruct {
    field1: String,
    field2: Option<u64>,
    #[serde(tag(value = "tag_value"))]
    tag: ()
}

#[serde(tag(value = "tag_value"))] is not an actual Serde-provided attribute, it's here just to express an idea. I'm aware that I can do all the serialization by myself, use remote, (de)serialize_with, etc., but these require a lot of boilerplate code.

The idea is that a tag field must exist, MyStruct serialized to JSON should be:

{
    "field1": "foo",
    "field2": 42,
    "tag": "tag_value"
}

Deserialization must fail if either "tag" field is missing or maps to a different value from "tag_value".

解决方案

Use a single variant enumeration:

use serde; // 1.0.104
use serde_json; // 1.0.48

#[derive(Debug, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
enum Tag {
    TagValue,
}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct MyStruct {
    field1: String,
    field2: Option<u64>,
    tag: Tag,
}

fn main() {
    let s = MyStruct {
        field1: "foo".to_string(),
        field2: Some(42),
        tag: Tag::TagValue,
    };

    // The tag is included when serializing
    println!("{:?}", serde_json::to_string(&s));

    // Tag is required when deserializing
    println!(
        "{:?}",
        serde_json::from_str::<MyStruct>(
            "{\"field1\":\"foo\",\"field2\":42,\"tag\":\"tag_value\"}"
        )
    );
    println!(
        "{:?}",
        serde_json::from_str::<MyStruct>("{\"field1\":\"foo\",\"field2\":42}")
    );

    // A bad tag fails
    println!(
        "{:?}",
        serde_json::from_str::<MyStruct>("{\"field1\":\"foo\",\"field2\":42,\"tag\":\"oops\"}")
    );
}

This prints

Ok("{\"field1\":\"foo\",\"field2\":42,\"tag\":\"tag_value\"}")
Ok(MyStruct { field1: "foo", field2: Some(42), tag: TagValue })
Err(Error("missing field `tag`", line: 1, column: 28))
Err(Error("unknown variant `oops`, expected `tag_value`", line: 1, column: 40))

(Permalink to the playground)

这篇关于有没有办法用 Serde 定义标签字段?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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