How change tuple in my case

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug)]
pub struct Msg {
    pub mydata: Mdt,
}


#[derive(Serialize, Deserialize, Debug)]
pub struct Mdt {
    pub info: Vec<(Option<String>,Option<i32>,Option<String>,Option<f64>,Option<i64>,Option<f64>,Option<f64>,Option<String>,Option<i32>,Option<String>)>,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {    

    pub const JS: &str =
    r#"{
         "mydata": {
    "info": [["txt1", 5000, "2023-04-20", -0.1234, 20230419131530, 0.5, -0.05, null, null, "txt2"]]
                       }
    }"#;
    
    let m: Msg = serde_json::from_str(&(JS))?;
    
    match &m.mydata.info[0].9 {
        Some(p) => println!("{:?}", p),
        None => println!("{:?}", "null")
    }
Ok(())
}

This example works when there are no more than 12 elements of info, because this is a limitation for tuple. How to change tuple (into a structure or array for enum) to work with the number of elements equal to 19. I do right for ten elements?

Serde implements Serialize/Deserialize for tuples up to a length of 16 elements. Everything beyond I'd use a tuple struct instead. Here an example with 20 fields:

use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug)]
pub struct Msg {
    pub mydata: Mdt,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Foo(
    Option<String>,
    Option<i32>,
    Option<String>,
    Option<f64>,
    Option<i64>,
    Option<f64>,
    Option<f64>,
    Option<String>,
    Option<i32>,
    Option<String>,
    Option<String>,
    Option<i32>,
    Option<String>,
    Option<f64>,
    Option<i64>,
    Option<f64>,
    Option<f64>,
    Option<String>,
    Option<i32>,
    Option<String>,
);

#[derive(Serialize, Deserialize, Debug)]
pub struct Mdt {
    pub info: Vec<Foo>,
}

// fn main() {
fn main() -> Result<(), Box<dyn std::error::Error>> {
    pub const JS: &str = r#"{
        "mydata": {
            "info": [["txt1", 5000, "2023-04-20", -0.1234, 20230419131530, 0.5, -0.05, null, null, "txt2", "txt1", 5000, "2023-04-20", -0.1234, 20230419131530, 0.5, -0.05, null, null, "txt2"]]
        }
    }"#;

    let m: Msg = serde_json::from_str(&(JS))?;

    match &m.mydata.info[0].9 {
        Some(p) => println!("{:?}", p),
        None => println!("{:?}", "null"),
    }
    Ok(())
}

Playground.

1 Like

Yes, it works for me, thanks.

fast response, cool

If I understand correctly
in my case the element can take given data type or null.

Another case.
How should the code be changed to accept any data type from:
i32, i64, f64, string and null
for each element.

Yes, that is what Option<T> allows as input.

Creating an untagged enum with a variant for each type you wish to support works:

use serde::{Deserialize, Serialize};

use serde_json::Value;

#[derive(Serialize, Deserialize, Debug)]
pub struct Msg {
    pub mydata: Mdt,
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(untagged)]
pub enum SupportedTypes {
    I32(i32),
    I64(i64),
    Float(f64),
    String(String),
    Null,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Mdt {
    pub info: Vec<SupportedTypes>,
}

fn main() {
    pub const JS: &str = r#"{
        "mydata": {
            "info": [null, "string", 0, 9223372036854775807, 0.0]
        }
    }"#;

    let m: Msg = serde_json::from_str(&(JS)).unwrap();

    println!("{m:?}");
}

Playground.

1 Like

Thank you very much!

1 Like

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.