Rust Serde JSON Examples

Rust Serde JSON Examples

This is a tutorial on how to use Serde JSON to serialize and deserialize data.

Introduction

Serde JSON is framework for serializing and deserializing Rust data structures efficiently and generically.

How to Install it

In your Cargo.toml declare serde_json as a dependency:

[dependencies]
serde_json = "1.0"

Data Representations

Serde provides ways to convert between the following representations of JSON data:

  1. Text data
  2. Untyped or Loosely typed representation
  3. Strongly typed data

Simple Examples

Example 1 - Work on Untyped JSON values

A string of JSON data can be parsed into a serde_json::Value by the serde_json::from_str function. There is also from_slice for parsing from a byte slice &[u8] and from_reader for parsing from any io::Read like a File or a TCP stream.

use serde_json::{Result, Value};

fn untyped_example() -> Result<()> {
    // Some JSON input data as a &str. Maybe this comes from the user.
    let data = r#"
        {
            "name": "John Doe",
            "age": 43,
            "phones": [
                "+44 1234567",
                "+44 2345678"
            ]
        }"#;

    // Parse the string of data into serde_json::Value.
    let v: Value = serde_json::from_str(data)?;

    // Access parts of the data by indexing with square brackets.
    println!("Please call {} at the number {}", v["name"], v["phones"][0]);

    Ok(())
}

fn main() {
    untyped_example().unwrap();
}

If you run it you will get;

Please call "John Doe" at the number "+44 1234567"

Example 2: Parsing JSON as strongly typed data structures

Serde provides a powerful way of mapping JSON data into Rust data structures largely automatically.

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

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

fn typed_example() -> Result<()> {
    // Some JSON input data as a &str. Maybe this comes from the user.
    let data = r#"
        {
            "name": "John Doe",
            "age": 43,
            "phones": [
                "+44 1234567",
                "+44 2345678"
            ]
        }"#;

    // Parse the string of data into a Person object. This is exactly the
    // same function as the one that produced serde_json::Value above, but
    // now we are asking it for a Person as output.
    let p: Person = serde_json::from_str(data)?;

    // Do things just like with any other Rust data structure.
    println!("Please call {} at the number {}", p.name, p.phones[0]);

    Ok(())
}

If you run you get:

Please call John Doe at the number +44 1234567

Example 3: Constructing JSON values

Serde JSON provides a json! macro to build serde_json::Value objects with very natural JSON syntax.

use serde_json::json;

fn main() {
    // The type of john is serde_json::Value
    let john = json!({
      "name": "John Doe",
      "age": 43,
      "phones": [
        "+44 1234567",
        "+44 2345678"
      ]
    });

    println!("first phone number: {}", john["phones"][0]);

    // Convert to a string of JSON and print it out
    println!("{}", john.to_string());
}

If you run you willget:

first phone number: "+44 1234567"
{"age":43,"name":"John Doe","phones":["+44 1234567","+44 2345678"]}

Example 4: Create JSON By serializing Data Structure

Using the serde_json::to_string you can convert a data structure to JSON string.

You can also use serde_json::to_vec to serialize to a Vec<u8> and serde_json::to_writer to serialize to any io::Write such as a File or a TCP stream.

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

#[derive(Serialize, Deserialize)]
struct Address {
    street: String,
    city: String,
}

fn print_an_address() -> Result<()> {
    // Some data structure.
    let address = Address {
        street: "10 Downing Street".to_owned(),
        city: "London".to_owned(),
    };

    // Serialize it to a JSON string.
    let j = serde_json::to_string(&address)?;

    // Print, write to a file, or send to an HTTP server.
    println!("{}", j);

    Ok(())
}

fn main() {
    print_an_address().unwrap();
}

If you run you will get:

{"street":"10 Downing Street","city":"London"}

Reference

Read more here

Serde JSON RPC Example

Step 1: Install

Declare your dependencies in your Cargo.toml as follows:

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

Step 2: Write Code

here is the full code:

use serde::{Serialize, Deserialize};
use serde::{Serializer, Deserializer};
use serde_json::Value;
use serde_json::json;
use serde::de::Error;

#[derive(Serialize, Deserialize, Debug)]
#[serde(tag = "method", content = "params")]
#[serde(rename_all = "snake_case")]
enum MyRequests {
    ItemAtIndex { index: usize },
    Length,
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(tag = "method", content = "params")]
#[serde(rename_all = "snake_case")]
enum MyNotifications {
    InsertItem { item: Value, index: usize },
    ShrinkToFit { }
}

#[derive(Debug)]
enum JsonRpc<N, R> {
    Request(usize, R),
    Notification(N),
}

impl<N, R> Serialize for JsonRpc<N, R>
    where N: Serialize,
          R: Serialize
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        match *self {
            JsonRpc::Request(id, ref r) => {
                let mut v = serde_json::to_value(r).map_err(serde::ser::Error::custom)?;
                v["id"] = json!(id);
                v.serialize(serializer)
            }
            JsonRpc::Notification(ref n) => n.serialize(serializer),
        }
    }
}

impl<'de, N, R> Deserialize<'de> for JsonRpc<N, R>
    where N: Deserialize<'de>,
          R: Deserialize<'de>
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer<'de>
    {
        #[derive(Deserialize)]
        struct IdHelper {
            id: Option<usize>,
        }

        let v = Value::deserialize(deserializer)?;
        let helper = IdHelper::deserialize(&v).map_err(Error::custom)?;
        match helper.id {
            Some(id) => {
                let r = R::deserialize(v).map_err(Error::custom)?;
                Ok(JsonRpc::Request(id, r))
            }
            None => {
                let n = N::deserialize(v).map_err(Error::custom)?;
                Ok(JsonRpc::Notification(n))
            }
        }
    }
}

fn main() {
    let j = r#"{
        "id": 42,
        "method": "item_at_index",
        "params": {
            "index": 5
        }
    }"#;
    let k = r#"{
        "method": "insert_item",
        "params": {
            "index": 5,
            "item": 42
        }
    }"#;
    let l = r#"{
        "method": "shrink_to_fit",
        "params": {}
    }"#;

    type T = JsonRpc<MyNotifications, MyRequests>;
    println!("{:?}", serde_json::from_str::<T>(j).unwrap());
    println!("{:?}", serde_json::from_str::<T>(k).unwrap());
    println!("{:?}", serde_json::from_str::<T>(l).unwrap());
}

Step 3: Run

Run the code above and you will get:

Request(42, ItemAtIndex { index: 5 })
Notification(InsertItem { item: Number(42), index: 5 })
Notification(ShrinkToFit)

Reference

Find the download link below:

Number Link
1. Download example
2. Follow code author

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *