问题描述
我遇到的一个 API 的 JSON 结构很差。有人认为发回一个看起来像这样的列表是个好主意
features: [
"First one","second one",{
"feature": "third one","hasAdditionalImpact": true
},"forth one"
]
struct MyStruct {
SensibleData: String,SensibleTruthy: bool,features: serde_json::Value,}
这无助于我规范化和验证数据。
features: [
{
"feature": "First one","hasAdditionalImpact": false
},{
"feature": "second one","hasAdditonalImpact": false
},{
"feature": "forth one","hasAdditionalImpact": false
}
]
我看到 type_name 可能可用于检查类型并在由 serde_json
解析后进行后处理,但我也看到 type_name
用于诊断目的,所以我'宁愿不将其用于此目的。
解决方法
看起来你的 JSON 中的特性有两种形式;一个明确的对象和一个简化的形式,其中一些字段是默认的或未命名的。您可以使用这样的 eum 对其进行建模:
#[derive(Deserialize,Debug)]
#[serde(untagged)]
enum Feature {
Simple(String),Explicit {
feature: String,#[serde(rename = "hasAdditionalImpact")]
has_additional_impact: bool,}
}
#[serde(untagged)]
属性意味着它将尝试按顺序反序列化为每个变体,直到成功为止。
如果枚举会很烦人,您可以将它们全部转换为相同的结构,使用默认值,使用 #[serde(from)]
并提供 From
转换:
#[derive(Deserialize,Debug)]
#[serde(untagged)]
enum FeatureSource {
Simple(String),},}
#[derive(Deserialize,Debug)]
#[serde(from = "FeatureSource")]
struct Feature {
feature: String,has_additional_impact: bool,}
impl From<FeatureSource> for Feature {
fn from(other: FeatureSource) -> Feature {
match other {
FeatureSource::Simple(feature) => Feature {
feature,has_additional_impact: false,FeatureSource::Explicit {
feature,has_additional_impact,} => Feature {
feature,}
}
}
FeatureSource
仅用作中间表示,并在您的其余代码看到它之前转换为 Feature
。