Serialization

Serialization with serde

serde serde-crates.io serde-github serde-lib.rs

serde is the de facto standard serialization library. Use in conjunction with sub-crates like serde_json for the specific format that you are using.

//! Demonstrates basic serialization and deserialization using `serde`.
use serde::Deserialize;
use serde::Serialize;

// Define a struct and derive the `Serialize` and `Deserialize` traits.
#[derive(Serialize, Deserialize, Debug)]
struct Person {
    // Rename the fields during serialization and deserialization.
    #[serde(rename = "first_name")]
    first: String,
    #[serde(rename = "last_name")]
    last: String,
    // Skip serializing the `age` field if it is None.
    #[serde(skip_serializing_if = "Option::is_none")]
    age: Option<u8>,
}

fn main() {
    // Create an instance of the struct.
    let person = Person {
        first: String::from("John"),
        last: String::from("Doe"),
        age: Some(30),
    };

    // Serialize the struct to a JSON string.
    let json = serde_json::to_string(&person).unwrap();
    println!("Serialized: {}", json);

    // Deserialize the JSON string back to a struct.
    let deserialized_person: Person = serde_json::from_str(&json).unwrap();
    println!("Deserialized: {:?}", deserialized_person);
}

(De)serialize JSON

serde_json serde_json-crates.io serde_json-github serde_json-lib.rs

serde-json

use serde::Deserialize;
use serde::Serialize;

// Define a struct `Person`.
// The `Serialize` and `Deserialize` derive macros automatically implement the
// `Serialize` and `Deserialize` traits for `Person`.
#[derive(Serialize, Deserialize, Debug)]
struct Person {
    name: String,
    age: u8,
    email: String,
}

fn main() {
    // Create an instance of `Person`.
    let person = Person {
        name: "Alice".to_string(),
        age: 30,
        email: "alice@example.com".to_string(),
    };

    // Serialize the `Person` instance to a JSON string.
    let json_string = serde_json::to_string(&person).unwrap();
    println!("Serialized JSON: {}", json_string);

    // Deserialize the JSON string back into a `Person` instance.
    let deserialized_person: Person =
        serde_json::from_str(&json_string).unwrap();
    println!("Deserialized person: {:?}", deserialized_person);
}

Handle Unknown Fields When Deserializing, with serde-ignored

serde-ignored serde-ignored-crates.io serde-ignored-github serde-ignored-lib.rs

serde-ignored

//! `serde_ignored` is a crate that helps you handle unknown fields when
//! deserializing with `serde`. It's useful when you want to ignore fields
//! that are present in the input but not defined in your struct.
//!
//! This example demonstrates how to use `serde_ignored` to deserialize a JSON
//! object into a struct while ignoring any unknown fields.
//!
//! In `Cargo.toml`, add:
//! ```toml
//! [dependencies]
//! serde = { version = "1.0.217", features = ["derive"] } # or latest
//! serde_ignored = "0.1.10"
//! serde_json = "1.0.138"
//! ```
use serde::Deserialize;

#[allow(dead_code)]
#[derive(Deserialize, Debug)]
struct MyStruct {
    field1: i32,
    field2: String,
}

fn main() {
    let json_data = r#"
    {
        "field1": 42,
        "field2": "Hello, world!",
        "unknown_field": "This will be ignored",
        "another_unknown": 123
    }
    "#;

    // Create a vector to store ignored fields.
    let mut ignored_fields = Vec::new();

    // Deserialize the JSON data, collecting ignored fields.
    let result: Result<MyStruct, _> = serde_ignored::deserialize(
        &mut serde_json::Deserializer::from_str(json_data),
        |path: serde_ignored::Path| {
            println!("Ignored field found: {}", path);
            ignored_fields.push(path.to_string());
        },
    );

    // Check the result of deserialization.
    match result {
        Ok(my_struct) => {
            println!("Deserialized struct: {:?}", my_struct);
            println!("All ignored fields: {:?}", ignored_fields);
        }
        Err(e) => {
            println!("Error deserializing: {}", e);
        }
    }
}

monostate

monostate monostate-crates.io monostate-github monostate-lib.rs

The monostate library implements a type macro for a zero-sized type that is Serde deserializable only from one specific value.

//! This example demonstrates how to use the `monostate` crate with `serde` to
//! deserialize untagged enums where certain fields must have specific values.
//!
//! The default representation for enums in Serde is called the externally
//! tagged enum representation: {"Success": {"success": "..."}}
//! In JSON and other self-describing formats, this externally tagged
//! representation is often not ideal for readability. That can be changed with
//! e.g. the `#[serde(untagged)]` attribute: the untagged JSON representation is
//! {"success": "..."}. See https://serde.rs/enum-representations.html
//!
//! The `monostate` crate implements the `MustBe` macro, which makes fields
//! `serde` deserializable only if they have one specific value. This is
//! particularly helpful when deserializing untagged enums, as it allows you to
//! differentiate between variants based on the values of their fields.
use monostate::MustBe;
use serde::Deserialize;

/// Represents a response that can be either a success or an error.
#[derive(Deserialize)]
#[serde(untagged)]
pub enum ApiResponse {
    Success {
        success: MustBe!(true),
    },
    Error {
        success: MustBe!(false),
        _message: String,
    },
}

fn main() {
    let success = "{\"success\":true}";
    let response: ApiResponse = serde_json::from_str(success).unwrap();

    match response {
        ApiResponse::Success {
            success: MustBe!(true),
        } => {}
        ApiResponse::Error { .. } => panic!(),
    }

    let error = "{\"success\":false,\"_message\":\"...\"}";
    let response: ApiResponse = serde_json::from_str(error).unwrap();
    match response {
        ApiResponse::Error {
            success: MustBe!(false),
            ..
        } => {}
        ApiResponse::Success { .. } => panic!(),
    }
}
// Example adapted from https://github.com/dtolnay/monostate/blob/master/tests/test.rs