Readers like you help support MUO. When you make a purchase using links on our site, we may earn an affiliate commission. Read More.

JSON (JavaScript Object Notation) has emerged as a popular data interchange format in software development due to its simplicity, readability, and widespread support across various programming languages. JSON is a lightweight alternative to XML for transmitting data between a server and a web application or between different software system components.

MAKEUSEOF VIDEO OF THE DAY
SCROLL TO CONTINUE WITH CONTENT

One of the key aspects of working with JSON is the process of serialization and deserialization which allows you to convert JSON data into a structured format that you can easily manipulate within your programs. Most times, if you want to work with JSON in other languages, you may need to serialize and deserialize the JSON data into the language’s built-in data structures.

Getting Started With Serde

Serde (serialization and deserialization) is a widely-used Rust library that provides a framework for converting Rust data structures into formats for storage, transmission, sharing, and others.

Serde enables seamless conversion between Rust data types and various data interchange formats, including JSON, YAML, BSON, CBOR, MessagePack, and others.

Serde's primary focus is making the serialization and deserialization process as simple and efficient as possible while maintaining strong typing and safety features.

Add these directives to the dependencies section of your Cargo.toml file to install and use Serde as a third-party dependency with Cargo.

 [dependencies]
serde = { version = "1.0.159" , features = ["derive"] }
serde_json = "1.0.96"

You’ll need both the serde and serde_json crates to interact with JSON. The serde crate provides the core functionalities, and the serde_json crate is a specific implementation of Serde for working with JSON.

Here’s how you can import the serde_json crate and the Serialize and Deserialize modules from the serde crate:

 use serde::{Serialize, Deserialize};
use serde_json;

Overall, Serde is a powerful tool you’ll need in your development arsenal if you’re working with JSON in Rust.

Data Serialization With Serde

The JSON serialization process entails converting a Rust type (custom or built-in) to JSON for other operations. Serde provides a set of attributes you can use with Rust struct to enable precise control over the serialization process, including the #[derive(Serialize)] attribute that allows you to generate serialization code for your data structures and convert your Rust struct to JSON.

Consider this struct representing a person’s bio-data; here’s how you can import and use the Serialize attribute on the struct:

 use serde::{Serialize, Deserialize};
use serde_json;

#[derive(Serialize)]
struct Person {
    name: String,
    age: u32,
}

By annotating the Person struct with the [#derive(Serialize)], you’re telling Serde to generate the necessary serialization code for the Person struct automatically.

Here’s how you can serialize an instance of the Person struct to JSON:

 use serde::{Serialize};
use serde_json;

fn main() {
    // declaration of the Person struct instance with the name and age fields
    let person = Person {
        name: "Chukwuemeriwo".to_string(),
        age: 28,
    };

    // serializes the person struct to JSON using the serde_json library
    let json = serde_json::to_string(&person).expect("Serialization failed");

    // prints the serialized JSON string
    println!("Serialized JSON: {}", json);
}

In the main function, the serde_json crate serializes the person object. The to_string function takes a reference to the person object and returns a JSON string representing the serialized data.

Finally, the main function prints the serialized JSON to the console.

result of printing the serialized JSON

The serde and serde_json are versatile, you can also serialize arrays with serde.

 use serde::{Serialize, Deserialize};
use serde_json;

#[derive(Serialize)]
struct Coordinates {
    x: f32,
    y: f32,
}

fn main() {
    let points = vec![
        Coordinates { x: 1.0, y: 2.0 },
        Coordinates { x: 3.5, y: 4.5 },
    ];

    let json = serde_json::to_string(&points).expect("Serialization failed");

    println!("Serialized JSON: {}", json); // Print the serialized JSON string
}

The points variable is a vector of Coordinates structs representing points on a plane. Applying the Serialize attribute to the Coordinates struct allows you to serialize the vector to JSON effortlessly.

Additionally, you can serialize enums into JSON with serde like you serialize structs and vectors.

 use serde::{Serialize, Deserialize};
use serde_json;

#[derive(Serialize, Deserialize)]
enum Animal {
    Dog(String),
    Cat(u32),
    Bird,
}

fn main() {
    let dog = Animal::Dog("Rusty".to_string());

    let json = serde_json::to_string(&dog).expect("Serialization failed");

    println!("Serialized JSON: {}", json);
}

Depending on the variant, the serialization process adapts accordingly (in this case, the Animal::Dog variant includes a String field that Serde will serialize as a JSON string).

Data Deserialization With Serde

JSON deserialization is the process of transforming JSON data into native data types of a programming language. Serde provides a comprehensive framework for JSON deserialization that works on most built-in data types.

Similar to serialization, Serde offers attributes that you can use to annotate your Rust structs for the deserialization process. Two commonly used attributes for serialization are the #[derive(Deserialize)] and #[serde(rename = "json_field_name")] attributes.

The #[derive(Deserialize)] attribute automatically derives the deserialization implementation for your Rust struct types, while the #[serde(rename = "json_field_name")] attribute allows you to map struct fields to corresponding JSON field names.

Here’s how you can deserialize JSON data into a custom struct type with Serde:

 use serde::Deserialize;
use serde_json;

// defines a struct for Person with the Deserialize trait from Serde
#[derive(Deserialize)]
struct Person {
    #[serde(rename = "name")] // renames the field to "name"
    full_name: String,
    age: u32,
}

fn main() {
    let json_data = r#"
        {
            "name": "John Doe",
            "age": 30
        }
    "#;

    // deserializes the JSON data into a Person struct
    let person: Person = serde_json::from_str(json_data).unwrap();

    // Print the full name and age of the person
    println!("Name: {}", person.full_name);
    println!("Age: {}", person.age);
}

By annotating the Person struct with the #[derive(Deserialize)] attribute, you indicate that Serde can deserialize the struct from JSON. The #[serde(rename = "name")] attribute maps the name field in the JSON to the full_name field.

The from_str function deserializes the json_data variable into the person object, and the main function prints the fields to the console.

result of printing the JSON fields

Serde supports deserialization on various Rust data types, including primitive types, enums, nested structs, and collections.

Here’s how you can deserialize a JSON array into a Rust struct containing a vector field:

 use serde::Deserialize;

#[derive(Deserialize)]
struct Data {
    numbers: Vec<u32>,
}

fn main() {
    let json_data = r#"
        {
            "numbers": [1, 2, 3, 4, 5]
        }
    "#;

    let data: Data = serde_json::from_str(json_data).unwrap();

    for number in data.numbers {
        println!("Number: {}", number);
    }
}

The main function deserializes the json_data JSON content into the data variable, and the loop prints the elements in the vector.

You must ensure that you have the right data types and identifiers for a deserialization process.

Serde is a powerful library with many features and a simple API for serializing and deserializing data into different formats.

Serde is widely adopted in the Rust ecosystem, and many popular crates and frameworks have built-in support for Serde, including popular web frameworks like Actix, Warp, and Rocket and database ORMs like Diesel.