Serialization
Recipe | Crates | Categories |
---|---|---|
Serialization with serde | ||
(De)serialize JSON | ||
monostate | ||
Handle Unknown Fields When Deserializing, with serde-ignored |
Serialization with serde
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
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` 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
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