Serde 如何将数据反序列化为多个结构体之一?

4

有没有一种好的方法可以将JSON暂时反序列化为不同的结构体?在文档中找不到任何内容,不幸的是结构体有一个“tag”来区分,就像这个链接中描述的那样:如何有条件地将JSON反序列化为枚举的两个不同变体?

到目前为止,我的方法是这样的:

use aws_lambda_events::event::{
    firehose::KinesisFirehoseEvent, kinesis::KinesisEvent,
    kinesis_analytics::KinesisAnalyticsOutputDeliveryEvent,
};
use lambda::{lambda, Context};
use serde_json::Value;

type Error = Box<dyn std::error::Error + Send + Sync + 'static>;
enum MultipleKinesisEvent {
    KinesisEvent(KinesisEvent),
    KinesisFirehoseEvent(KinesisFirehoseEvent),
    KinesisAnalyticsOutputDeliveryEvent(KinesisAnalyticsOutputDeliveryEvent),
    None,
}

#[lambda]
#[tokio::main]
async fn main(event: Value, _: Context) -> Result<String, Error> {
    let multi_kinesis_event = if let Ok(e) = serde_json::from_value::<KinesisEvent>(event.clone()) {
        MultipleKinesisEvent::KinesisEvent(e)
    } else if let Ok(e) = serde_json::from_value::<KinesisFirehoseEvent>(event.clone()) {
        MultipleKinesisEvent::KinesisFirehoseEvent(e)
    } else if let Ok(e) = serde_json::from_value::<KinesisAnalyticsOutputDeliveryEvent>(event) {
        MultipleKinesisEvent::KinesisAnalyticsOutputDeliveryEvent(e)
    } else {
        MultipleKinesisEvent::None
    };

    // code below is just sample

    let s = match multi_kinesis_event {
        MultipleKinesisEvent::KinesisEvent(_) => "Kinesis Data Stream!",
        MultipleKinesisEvent::KinesisFirehoseEvent(_) => "Kinesis Firehose!",
        MultipleKinesisEvent::KinesisAnalyticsOutputDeliveryEvent(_) => "Kinesis Analytics!",
        MultipleKinesisEvent::None => "Not Kinesis!",
    };
    Ok(s.to_owned())
}
1个回答

4
你应该使用#untagged选项。
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug)]
struct KinesisFirehoseEvent {
    x: i32,
    y: i32
}

#[derive(Serialize, Deserialize, Debug)]
struct KinesisEvent(i32);

#[derive(Serialize, Deserialize, Debug)]
#[serde(untagged)]
enum MultipleKinesisEvent {
    KinesisEvent(KinesisEvent),
    KinesisFirehoseEvent(KinesisFirehoseEvent),
    None,
}

fn main() {
    let event = MultipleKinesisEvent::KinesisFirehoseEvent(KinesisFirehoseEvent { x: 1, y: 2 });

    // Convert the Event to a JSON string.
    let serialized = serde_json::to_string(&event).unwrap();

    // Prints serialized = {"x":1,"y":2}
    println!("serialized = {}", serialized);

    // Convert the JSON string back to a MultipleKinesisEvent.
    // Since it is untagged 
    let deserialized: MultipleKinesisEvent = serde_json::from_str(&serialized).unwrap();

    // Prints deserialized = KinesisFirehoseEvent(KinesisFirehoseEvent { x: 1, y: 2 })
    println!("deserialized = {:?}", deserialized);
}

在 playground 中查看

文档: 无标签


1
非常感谢!文档中总有一些我错过的很棒的东西 :P - Cadu Bentzen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接