如何实现枚举变体与JSON null双向序列化且无需自定义反序列化函数
将JSON的null反序列化为单元式枚举变体(无需自定义反序列化函数)
已实现将单元式枚举变体Action::Delete序列化为JSON的null,现需无需编写专用反序列化函数,直接将JSON中的null反序列化为Action::Delete,同时保留Action::Create对数组格式Entry的正常反序列化能力。
解决方案
通过给Delete变体添加#[serde(deserialize_as = "Option<()>")]属性,配合枚举的#[serde(untagged)]属性,即可实现需求:
use serde::{Serialize, Deserialize}; use serde_json::from_str; #[derive(Serialize, Deserialize)] struct Entry(String, String); #[derive(Serialize, Deserialize)] #[serde(untagged)] enum Action { #[serde(serialize_with = "serde::ser::Serializer::serialize_none")] #[serde(deserialize_as = "Option<()>")] Delete, Create(Entry), } type Actions = Vec<Action>; #[test] fn this_works() { from_str::<Actions>(r#"[["id", "value"], []]"#).unwrap(); } #[test] fn this_now_works() { from_str::<Actions>(r#"[["id", "value"], null]"#).unwrap(); }
原理说明
#[serde(deserialize_as = "Option<()>")]:指定Delete变体按Option<()>的逻辑反序列化,Option<()>会自动将JSON的null解析为None,进而映射到单元变体Delete。#[serde(untagged)]:让serde忽略枚举标签,按变体类型匹配JSON值——Create(Entry)匹配数组格式的JSON,Delete匹配null。
若需保留Delete()带括号的单元变体写法,只需调整变体定义即可,属性无需修改:
#[derive(Serialize, Deserialize)] #[serde(untagged)] enum Action { #[serde(serialize_with = "serde::ser::Serializer::serialize_none")] #[serde(deserialize_as = "Option<()>")] Delete(), Create(Entry), }
内容的提问来源于stack exchange,提问作者Thomas W
相关产品推荐
相关产品推荐

