JSON is a commonly used data object composed of key-value pairs. This article will demonstrate through multiple examples how to parse JSON content in Rust and how to convert structs into JSON strings.

Rust's serde provides JSON serialization and deserialization capabilities;

Adding Dependencies

To use the serde library for parsing JSON text, you need to add serde and serde_json dependencies to your project:

Add the following lines to your Cargo.toml file:

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

Parsing JSON

Parsing Untyped JSON

Any valid JSON data can be converted into the serde_json::Value type, defined as follows:

enum Value {
    Null,
    Bool(bool),
    Number(Number),
    String(String),
    Array(Vec<Value>),
    Object(Map<String, Value>),
}

serde_json provides several functions for parsing various forms of JSON data:

  • serde_json::from_str - for parsing JSON strings;
  • serde_json::from_slice - for parsing byte slices &[u8];
  • serde_json::from_reader - reads and parses data from objects implementing the io::Read trait, such as files or TCP streams;

An example using serde_json::from_str:

fn main() {

    // JSON data as &str
    let data = r#"
        {
            "name": "James Bond",
            "age": 33,
            "pet_phrase": [
                "Bond, James Bond.",
                "Shaken, not stirred."
            ]
        }"#;

    // Convert to serde_json::Value
    let v: serde_json::Value = serde_json::from_str(data).unwrap();

    // Access data using square bracket indexing
    println!("NAME: {}\nAGE: {}\n\t{}\n\t{}",
        v["name"],
        v["age"],
        v["pet_phrase"][0],
        v["pet_phrase"][1],
    );
}

Program Output

NAME: "James Bond"
AGE: 33
        "Bond, James Bond."
        "Shaken, not stirred."

Parsing JSON into Custom Data Structures

serde provides Serialize and Deserialize traits to define serialization and deserialization behavior for data structures.

Modifying the previous example to use custom data structures with Serialize and Deserialize:

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
struct Person {
    name: String,
    age: u8,
    pet_phrase: Vec<String>,
}

fn main() {

    // JSON data as &str
    let data = r#"
        {
            "name": "James Bond",
            "age": 33,
            "pet_phrase": [
                "Bond, James Bond.",
                "Shaken, not stirred."
            ]
        }"#;

    // Convert to Person struct
    let p: Person = serde_json::from_str(data).unwrap();

    // Access struct fields directly
    println!("NAME: {}\nAGE: {}\n\t{}\n\t{}",
        p.name,
        p.age,
        p.pet_phrase[0],
        p.pet_phrase[1],
    );
}

This code produces the same output as the previous example, but this time we assigned the return value of serde_json::from_str to a custom Person type.

Errors will occur if the JSON data doesn't match the struct definition;

Converting Data Structures to JSON Strings

serde provides functions to convert data structures into JSON:

  • serde_json::to_string - converts data structures to JSON strings;
  • serde_json::to_vec - serializes data structures to Vec<u8>;
  • serde_json::to_writer - serializes to any object implementing the io::Write trait, such as files or TCP streams;

An example using serde_json::to_string:

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
struct Person {
    name: String,
    age: u8,
    pet_phrase: Vec<String>,
}

fn main() {

    let mut pp = Vec::new();
    pp.push("hello world".to_string());
    pp.push("perfcode.com".to_string());

    let p = Person {
        name: "ho".to_string(),
        age: 18,
        pet_phrase: pp,
    };

    // Serialize to JSON string
    let s = serde_json::to_string(&p).unwrap();

    println!("{}",s);
    
}

Program Output

{"name":"ho","age":18,"pet_phrase":["hello world","perfcode.com"]}

The json! Macro

serde provides a json! macro for naturally constructing serde_json::Value objects:

The .to_string() method can convert serde_json::Value objects into JSON strings:

use serde_json::json;

fn main() {

    let info = json!(
        {
            "name": "James Bond",
            "age": 33,
            "pet_phrase":[
                "Bond, James Bond.",
                "Shaken, not stirred."
                ]
        }
    );

    // Access data using square bracket indexing
    println!("NAME: {}\nAGE: {}\n\t{}\n\t{}",
        info["name"],
        info["age"],
        info["pet_phrase"][0],
        info["pet_phrase"][1],
    );

    // Serialize
    println!("{}",info.to_string());

}

Program Output

NAME: "James Bond"
AGE: 33
        "Bond, James Bond."
        "Shaken, not stirred."
{"age":33,"name":"James Bond","pet_phrase":["Bond, James Bond.","Shaken, not stirred."]}