根据 JSON 中的字段有条件地解码 JSON
Conditionally decoding JSON based on a field in the JSON
我从 API 收到 JSON,响应可以是 30 种类型之一。每种类型都有一组唯一的字段,但所有响应都有一个字段 type
说明它是哪种类型。
我的做法是使用serde。我为每种响应类型创建一个结构并使它们可解码。一旦我有了这个,我该如何选择哪个结构应该用于新收到的消息?
目前,我创建了另一个结构 TypeStruct
,其中只有 type
的一个字段。我将 JSON 解码为 TypeStruct
,然后根据类型值为接收到的消息选择适当的结构,然后再次解码消息。
我想摆脱这种解码重复。
您可以使用现有的枚举反序列化。我将逐步举例说明将您的格式反序列化为以下枚举:
#[derive(Debug, PartialEq, Eq, Deserialize)]
enum MyType {
A {gar: ()},
B {test: i32},
C {blub: String},
}
从一个例子开始json字符串:
let json = r#"{"type": "B", "test": 42}"#;
把它变成一个Value
枚举
let mut json: serde_json::Value = serde_json::from_str(json).unwrap();
删除 type
字段
let type_ = {
let obj = json.as_object_mut().expect("object");
let type_ = obj.remove("type").expect("`type` field");
if let serde_json::Value::String(s) = type_ {
s
} else {
panic!("type field not a string");
}
};
创建 "proper" 枚举 json。具有单个字段的结构,其中字段的名称是枚举变体,字段的值是变体值
let mut enum_obj = std::collections::BTreeMap::new();
enum_obj.insert(type_, json);
let json = serde_json::Value::Object(enum_obj);
使用生成的 json 反序列化器将 json 转换为您的枚举值
let obj: MyType = serde_json::from_value(json).unwrap();
我从 API 收到 JSON,响应可以是 30 种类型之一。每种类型都有一组唯一的字段,但所有响应都有一个字段 type
说明它是哪种类型。
我的做法是使用serde。我为每种响应类型创建一个结构并使它们可解码。一旦我有了这个,我该如何选择哪个结构应该用于新收到的消息?
目前,我创建了另一个结构 TypeStruct
,其中只有 type
的一个字段。我将 JSON 解码为 TypeStruct
,然后根据类型值为接收到的消息选择适当的结构,然后再次解码消息。
我想摆脱这种解码重复。
您可以使用现有的枚举反序列化。我将逐步举例说明将您的格式反序列化为以下枚举:
#[derive(Debug, PartialEq, Eq, Deserialize)]
enum MyType {
A {gar: ()},
B {test: i32},
C {blub: String},
}
从一个例子开始json字符串:
let json = r#"{"type": "B", "test": 42}"#;
把它变成一个
Value
枚举let mut json: serde_json::Value = serde_json::from_str(json).unwrap();
删除
type
字段let type_ = { let obj = json.as_object_mut().expect("object"); let type_ = obj.remove("type").expect("`type` field"); if let serde_json::Value::String(s) = type_ { s } else { panic!("type field not a string"); } };
创建 "proper" 枚举 json。具有单个字段的结构,其中字段的名称是枚举变体,字段的值是变体值
let mut enum_obj = std::collections::BTreeMap::new(); enum_obj.insert(type_, json); let json = serde_json::Value::Object(enum_obj);
使用生成的 json 反序列化器将 json 转换为您的枚举值
let obj: MyType = serde_json::from_value(json).unwrap();