【问题标题】:Serde Deserialize into one of multiple structs?Serde 反序列化为多个结构之一?
【发布时间】:2020-12-06 15:36:16
【问题描述】:

有没有一种很好的方法可以暂时将 JSON 反序列化为不同的结构?在文档中找不到任何内容,不幸的是,结构有“标签”来区分,如How to conditionally deserialize JSON to two different variants of an enum?

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

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())
}

【问题讨论】:

    标签: json rust serde


    【解决方案1】:

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

    【讨论】:

    • 非常感谢!我在文档中总是错过了一些很棒的东西:P
    猜你喜欢
    • 2022-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-22
    • 1970-01-01
    • 2022-11-10
    • 1970-01-01
    相关资源
    最近更新 更多