serde icon indicating copy to clipboard operation
serde copied to clipboard

Deserialize "unknown" values

Open dixpac opened this issue 3 years ago • 1 comments

Hi there!

I'm a rust newbie so maybe I'm missing something but I've following problem:

I'm using serde to deserialize JSON response into struct

#[derive(Debug, Deserialize)]
struct Message {
    channel: String,
    global_id: u128,
    message_id: i8,
    data: ???, <--- this could be different types
}

API that I'm working with can return different type for data attribute, for example:

// first example
[
    {
        "global_id": -1,
        "message_id": -1,
        "channel": "/__status",
        "data": {
            "/channel": 3
        }
    }
]

// second example
[
    {
        "global_id": 1510,
        "message_id": 3,
        "channel": "/channel",
        "data": "test"
    }
]

// third example
[
    {
        "global_id": 1510,
        "message_id": 3,
        "channel": "/channel",
        "data":  {
           "name": "Serde"
        }
    }
]

How can I represent this data attribute on the Message struct to accomodate this use-case?

✌️

dixpac avatar May 15 '22 16:05 dixpac

@dixpac hello! Maybe this will help?

use serde_json::Value;

#[derive(Debug, Deserialize)]
struct Message {
    channel: String,
    global_id: u128,
    message_id: i8,
    data: Value,
}

Example:


use serde_json::Value;
use serde::Deserialize;


const A1: &'static str = r#"

{
    "global_id": -1,
    "message_id": -1,
    "channel": "/__status",
    "data": {
        "/channel": 3
    }
}
"#;

const A2: &'static str = r#"
{
    "global_id": -1,
    "message_id": -1,
    "channel": "/__status",
    "data": "test"
}
"#;

const A3: &'static str = r#"
{
    "global_id": -1,
    "message_id": -1,
    "channel": "/__status",
    "data": {
        "name": 3
    }
}
"#;

#[derive(Debug, Deserialize)]
struct Message {
    channel: String,
    global_id: i8,
    message_id: i8,
    data: Value,
}

fn main() {
    let a1: Message = serde_json::from_str(A1).unwrap();
    let a2: Message = serde_json::from_str(A2).unwrap();
    let a3: Message = serde_json::from_str(A3).unwrap();
    println!("{:?}", a1);  // Message { channel: "/__status", global_id: -1, message_id: -1, data: Object({"/channel": Number(3)}) }
    println!("{:?}", a2);  // Message { channel: "/__status", global_id: -1, message_id: -1, data: String("test") }
    println!("{:?}", a3);  // Message { channel: "/__status", global_id: -1, message_id: -1, data: Object({"name": Number(3)}) }
}

ikrivosheev avatar Jun 08 '22 14:06 ikrivosheev