Serde反序列化为多个结构之一?

Serde Deserialize into one of multiple structs?

是否有一种很好的方法可以暂时将 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())
}

您应该使用 #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);
}

See in playground

文档:Untagged