Skip to content

Instantly share code, notes, and snippets.

@max-itzpapalotl
Last active January 26, 2024 19:29
Show Gist options
  • Save max-itzpapalotl/5e61dbf84ce0542d1ab5770953d7ae59 to your computer and use it in GitHub Desktop.
Save max-itzpapalotl/5e61dbf84ce0542d1ab5770953d7ae59 to your computer and use it in GitHub Desktop.
18. JSON and serde

18. JSON and serde

Rust has excellent serialization and deserialization support via the serde crate: https://docs.rs/serde/latest/serde/

For the examples in this video we need the following in Cargo.toml:

[dependencies]
serde = { version = "1.0.195", features = ["derive"] }
serde_json = "1.0.111"

Working with untyped JSON values

The serde_json::Value type and the json! macro:

use serde_json::json;
use std::collections::HashMap;

fn main() {
    let j = json!({ "a": 12, "b": true, "c": null, "d": [12, "xyz"],
                    "e": { "name": "Hello", "first": "Heinz" } });
    println!("{}", j);
    let s = j.to_string();
    println!("{}", s);
    let a = &j["e"];
    println!("{}", a);

    let n = json!(null);
    let t = json!(true);
    let f = json!(false);
    let j = json!(-3);
    let i = json!(12.3);
    let s = json!("abc");
    let a = json!([1]);
    let m = json!({"a":12});
    println!("{n} {t} {f} {j} {i} {s} {a} {m}");

    let l = json!(vec![1, 2, 3]);
    let h = json!(HashMap::from([("a", 12), ("b", 13)]));
    println!("{l} {h}");
}

Parsing from string slices

We can parse JSON directly from string slices into Values:

use serde_json::{from_str, Value};

fn main() {
    let j = from_str::<Value>(
        r#"{ "a": 12, "b": true, "c": null, "d": [12, "xyz"],
             "e": { "name": "Hello", "first": "Heinz" } }
          "#).unwrap();
    println!("{}", j);
    let n : Value = from_str("null").unwrap();
    let t : Value = from_str("true").unwrap();
    let f : Value = from_str("false").unwrap();
    let j : Value = from_str("-3").unwrap();
    let i : Value = from_str("12.3").unwrap();
    let s : Value = from_str(r#""abc""#).unwrap();
    let a : Value = from_str("[1]").unwrap();
    let m : Value = from_str(r#"{"a":12}"#).unwrap();
    println!("{n} {t} {f} {j} {i} {s} {a} {m}");
    let x : serde_json::Result<Value> = from_str("[12}");
    println!("{:?}", x);
    match x {
        Err(e) => { println!("{}", e); }
        Ok(v) => { println!("{}", v); }
    };
}

Matching on Values

The match expression is useful for JSON Values:

use serde_json::{json, Value};

fn main() {
    let j = json!({ "a": 12, "b": true, "c": null, "d": [12, "xyz"],
                    "e": { "name": "Hello", "first": "Heinz" } });
    let i = json!(-3);
    let s = json!("abc");
    match i {
        Value::Number(n) => println!("{n}"),
        _ => println!("Something else"),
    };
    match s {
        Value::String(ss) => println!("{ss}"),
        _ => println!("Something else"),
    };
    match &j["d"][1] {
        Value::String(ss) => println!("{ss}"),
        _ => println!("Something else"),
    };
}

Serialization and Deserialization of deserialization

use serde::{Serialize, Deserialize};

#[derive(Debug, Serialize, Deserialize)]
struct Person{
    pub name: String,
    pub age: u16,
    pub hobbies: Vec<String>,
}

fn main() {
    let p = Person{name: "Max".to_string(), age: 54,
                   hobbies: vec!["hacking".to_string(), "sailing".to_string()] };
    let s = serde_json::to_string(&p).unwrap();
    println!("Serialization: {s}");
    let q : Person = serde_json::from_str(&s).unwrap();
    println!("Deserialized: {:?}", q);
    let e : serde_json::Result<Person> = serde_json::from_str(r#"
        {"name": "Max", "agex": 12, "hobbies": []} "#);
    println!("Error: {e:?}");
}

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment