Getting started with Rust and JSON

I'm new to Rust and want to understand its concepts, that seem to be somewhat different to other languages.

Consider the following JSON, that I want to extract all objects from:

{
    "widget": {
        "debug": "on",
        "window": {
            "title": "Sample Konfabulator Widget",
            "name": "main_window",
            "width": 500,
            "height": 500
        },
        "image": {
            "src": "Images/Sun.png",
            "name": "sun1",
            "hOffset": 250,
            "vOffset": 250,
            "alignment": "center"
        },
        "text": {
            "data": "Click Here",
            "size": 36,
            "style": "bold",
            "name": "text1",
            "hOffset": 250,
            "vOffset": 100,
            "alignment": "center",
            "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
        }
    }
}

Here's a sample PHP code that illustrates the task:

function walkObject( $name, $x, &$result ): void {
	if( !is_object( $x ) ) return;
	$result[] = $name;
	foreach( $x as $name => $field )
		walkObject( $name, $field, $result );
}

$json = file_get_contents( '/media/sf_shared/test.json' );
$object = json_decode( $json );
$result = [];
walkObject( 'root', $object, $result );
print json_encode( $result ) . PHP_EOL;

Here's its output:
["root","widget","window","image","text"]

Now when I try to achieve the same in Rust, I face the following questions:

  • What is the recommended JSON parser that I should use for easy content manipulation?
  • How do I "walk" the JSON tree?
  • How do I test if a particular JSON element is an "object", "array", or "primitive"?

serde_json is the most used Json library in the Rust ecosystem. It represents arbitrary Json with its Value type, which you can use to index into/walk the Json structure and test what type an element is. It will be more verbose than your PHP version due to Rust's stricter typing though. Alternatively to using serde_json::Value, serde, the most used framework for serialisation in Rust and underlying the serde_json library, allows you to parse Json into native types (like primitive types or your own structs and enums).

1 Like

You should be aware that you usually don't do this in strongly-typed languages. Rather than deserializing into an associative array (PHP) or an object (Python, JavaScript), in strongly-typed languages you deserialize JSON into in-memory representations represented using the type system.

To give you an example, this JSON:

{
  "username": "duzenko",
  "created_at": "2025-04-22T10:11:23.005Z"
}

You would deserialize it into this:

struct User(username: UserName, created_at: DateTime<Utc>)

struct UserName(String)

To do this, the most popular library for de/serialization is Serde, which has a specific implementation for JSON named serde_json.

2 Likes

What if the JSON is specifically untyped/unstructured?

Can you give the methods that correspond to what I used in the PHP snippet?

You would do as @jofas said. Using serde_json's AST.

Value (see the doc that was linked) is a Rust enum, so to check for different Json value types you do a match on the enum. If you're not familiar with match, see:

To give you an idea about how Rust code typically looks, I translated your code almost-one-to-one:

fn walk_object(name: &str, x: Value, result: &mut Vec<String>) {
    let Value::Object(x) = x else { return };
    result.push(name.to_string());
    for (name, field) in x {
        walk_object(&name, field, result);
    }
}

fn main() {
    let object: Value = serde_json::from_str(JSON).unwrap();
    let mut result = vec![];
    walk_object("root", object, &mut result);
    println!("{:?}", result);
}

This is using the serde_json library, which is the de-facto standard. Here's a link to the playground so that you can try yourself: Rust Playground

[1]


  1. By default, serde_json does not store the order of the keys of an object. (It uses a HashMap). This alignes with the standard RFC 8259: The JavaScript Object Notation (JSON) Data Interchange Format "An object is an unordered collection". If the order of the keys is important, use an array instead. If you really think the order is important, reconsider if using json is the right tool for the job. If you really really need the order of keys, serde_json has a feature preserve_order that you can activate.] â†Šī¸Ž

5 Likes

Alternative using an iterator:

I intentionally removed the "root" name.

With serde_json:

use serde::Deserialize;
use serde_json::Result;

#[derive(Deserialize, Debug)]
struct Acme{nose: String}

fn main() -> Result<()> {
    let data = r#"{"nose": "cuke"}"#;
    let gizmo: Acme = serde_json::from_str(data)?;
    dbg!(&gizmo);
    println!("{}", gizmo.nose);
    Ok(())
}

Yields:

[gizmo/src/bin/jsons.rs:10:5] &gizmo = Acme {                                                 
     nose: "cuke",                                                                             
}                                                                                             
cuke                                                                                          

There is the standard way to operate with JSON in Rust. Just learn it. However if you have "Apple" vibe to think differently, you can try my JSON parser.

Major advantage of Rust for me, is the ability to think differently, for example, if you need BASE64 encoder, then you can get an absolutely beautiful decoder with over 7 mills downloads and over hundred forks. But if you want to get a real taste of Rust, then you can try my version and get rusty.