Deserializing an unknown enum using serde

Why does this code not deserialize the messages correctly?

The first message received is expected to fail, because the data field = {}, but after that the data field matches the Trade structure which is part of the flattened enum Data.

What am I doing wrong?

Here is the output:

***> {"event":"bts:subscription_succeeded","channel":"live_trades_btcusd","data":{}}
===> Error("no variant of enum Data found in flattened data", line: 1, column: 79)
***> {"data":{"id":220315257,"timestamp":"1644180636","amount":0.03208,"amount_str":"0.03208000","price":41586.11,"price_str":"41586.11","type":0,"microtimestamp":"1644180636419000","buy_order_id":1455495830577152,"sell_order_id":1455495778422789},"channel":"live_trades_btcusd","event":"trade"}
===> Error("no variant of enum Data found in flattened data", line: 1, column: 290)
***> {"data":{"id":220315276,"timestamp":"1644180648","amount":0.02037389,"amount_str":"0.02037389","price":41586.11,"price_str":"41586.11","type":1,"microtimestamp":"1644180648235000","buy_order_id":1455495864238080,"sell_order_id":1455495878971395},"channel":"live_trades_btcusd","event":"trade"}
use serde::{Deserialize, Serialize};
use serde_json::json;
use tungstenite::{connect, Message};
use url::Url;

#[derive(Serialize, Deserialize, Debug)]
enum Data {
    None,
    Trade(Trade),
}

#[derive(Serialize, Deserialize, Debug)]
struct Msg {
    channel: String,
    event: String,

    #[serde(flatten)]
    data: Data,
}


#[derive(Serialize, Deserialize, Debug)]
struct Trade {
    id: u32,
    amount: f32,
    amount_str: String,
    buy_order_id: u64,
    microtimestamp: String,
    price: f32,
    price_str: String,
    sell_order_id: u64,
    timestamp: String,
    #[serde(rename = "type")]
    _type: u8,
}

fn main() {
    let (mut socket, _response) =
        connect(Url::parse("wss://ws.bitstamp.net").unwrap()).expect("Can't connect");

    socket
        .write_message(
            Message::Text(
                json!({
                    "event": "bts:subscribe",
                    "data": {
                        "channel": "live_trades_btcusd"
                    }
                })
                .to_string(),
            )
            .into(),
        )
        .expect("Error sending message");

    loop {
        let msg = socket.read_message().expect("Error reading message");
        println!("***> {}", msg);
        let result: Result<Msg, serde_json::Error> = serde_json::from_str(msg.to_text().unwrap());
        
        let _value = match result {
            Ok(msg) => {
                println!("---> {:?}", msg);
            }
            Err(err) => {
                println!("===> {:?}", err);
                continue;
            }
        };
        
    }
}

Try removing the #[serde(flatten)].

I solved it by both removing the #[serde(flatten)] and also adding #[serde(untagged)]. Thanks for the help!

#[derive(Serialize, Deserialize, Debug)]
#[serde(untagged)]
enum Data {
    Trade(Trade),
    Order(Order),
    None {},
}

#[derive(Serialize, Deserialize, Debug)]
struct Msg {
    channel: String,
    event: String,
    data: Data,
}

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.