Get JSON values quickly - JSON parser for Rust

Overview

GJSON
GJSON Playground

get json values quickly

GJSON is a Rust crate that provides a fast and simple way to get values from a json document. It has features such as one line retrieval, dot notation paths, iteration, and parsing json lines.

This library is uses the identical path syntax as the Go version.

Getting Started

Usage

Put this in your Cargo.toml:

[dependencies]
gjson = "0.7"

Get a value

Get searches json for the specified path. A path is in dot syntax, such as "name.last" or "age". When the value is found it's returned immediately.

const JSON: &str = r#"{"name":{"first":"Janet","last":"Prichard"},"age":47}"#;

fn main() {
    let value = gjson::get(JSON, "name.last");
    println!("{}", value);
}

This will print:

Prichard

Path Syntax

Below is a quick overview of the path syntax, for more complete information please check out GJSON Syntax.

A path is a series of keys separated by a dot. A key may contain special wildcard characters '*' and '?'. To access an array value use the index as the key. To get the number of elements in an array or to access a child path, use the '#' character. The dot and wildcard characters can be escaped with '\'.

{
  "name": {"first": "Tom", "last": "Anderson"},
  "age":37,
  "children": ["Sara","Alex","Jack"],
  "fav.movie": "Deer Hunter",
  "friends": [
    {"first": "Dale", "last": "Murphy", "age": 44, "nets": ["ig", "fb", "tw"]},
    {"first": "Roger", "last": "Craig", "age": 68, "nets": ["fb", "tw"]},
    {"first": "Jane", "last": "Murphy", "age": 47, "nets": ["ig", "tw"]}
  ]
}
"name.last"          >> "Anderson"
"age"                >> 37
"children"           >> ["Sara","Alex","Jack"]
"children.#"         >> 3
"children.1"         >> "Alex"
"child*.2"           >> "Jack"
"c?ildren.0"         >> "Sara"
"fav\.movie"         >> "Deer Hunter"
"friends.#.first"    >> ["Dale","Roger","Jane"]
"friends.1.last"     >> "Craig"

You can also query an array for the first match by using #(...), or find all matches with #(...)#. Queries support the ==, !=, <, <=, >, >= comparison operators and the simple pattern matching % (like) and !% (not like) operators.

friends.#(last=="Murphy").first    >> "Dale"
friends.#(last=="Murphy")#.first   >> ["Dale","Jane"]
friends.#(age>45)#.last            >> ["Craig","Murphy"]
friends.#(first%"D*").last         >> "Murphy"
friends.#(first!%"D*").last        >> "Craig"
friends.#(nets.#(=="fb"))#.first   >> ["Dale","Roger"]

Value Type

To convert the json value to a Rust type:

value.i8()
value.i16()
value.i32()
value.i64()
value.u8()
value.u16()
value.u32()
value.u64()
value.f32()
value.f64()
value.bool()
value.str()    // a string representation
value.json()   // the raw json

handy functions that work on a value:

value.kind()             // String, Number, True, False, Null, Array, or Object
value.exists()           // returns true if value exists in JSON.
value.get(path: &str)    // get a child value
value.each(|key, value|) // iterate over child values

64-bit integers

The value.i64() and value.u64() calls are capable of reading all 64 bits, allowing for large JSON integers.

value.i64() -> i64   // -9223372036854775808 to 9223372036854775807
value.u64() -> u64   // 0 to 18446744073709551615

Modifiers and path chaining

A modifier is a path component that performs custom processing on the json.

Multiple paths can be "chained" together using the pipe character. This is useful for getting values from a modified query.

For example, using the built-in @reverse modifier on the above json document, we'll get children array and reverse the order:

"children|@reverse"           >> ["Jack","Alex","Sara"]
"children|@reverse|0"         >> "Jack"

There are currently the following built-in modifiers:

  • @reverse: Reverse an array or the members of an object.
  • @ugly: Remove all whitespace from a json document.
  • @pretty: Make the json document more human readable.
  • @this: Returns the current element. It can be used to retrieve the root element.
  • @valid: Ensure the json document is valid.
  • @flatten: Flattens an array.
  • @join: Joins multiple objects into a single object.

Modifier arguments

A modifier may accept an optional argument. The argument can be a valid JSON document or just characters.

For example, the @pretty modifier takes a json object as its argument.

@pretty:{"sortKeys":true} 

Which makes the json pretty and orders all of its keys.

{
  "age":37,
  "children": ["Sara","Alex","Jack"],
  "fav.movie": "Deer Hunter",
  "friends": [
    {"age": 44, "first": "Dale", "last": "Murphy"},
    {"age": 68, "first": "Roger", "last": "Craig"},
    {"age": 47, "first": "Jane", "last": "Murphy"}
  ],
  "name": {"first": "Tom", "last": "Anderson"}
}

The full list of @pretty options are sortKeys, indent, prefix, and width. Please see Pretty Options for more information.

JSON Lines

There's support for JSON Lines using the .. prefix, which treats a multilined document as an array.

For example:

{"name": "Gilbert", "age": 61}
{"name": "Alexa", "age": 34}
{"name": "May", "age": 57}
{"name": "Deloise", "age": 44}
..#                   >> 4
..1                   >> {"name": "Alexa", "age": 34}
..3                   >> {"name": "Deloise", "age": 44}
..#.name              >> ["Gilbert","Alexa","May","Deloise"]
..#(name="May").age   >> 57

Get nested array values

Suppose you want all the last names from the following json:

{
  "programmers": [
    {
      "firstName": "Janet", 
      "lastName": "McLaughlin", 
    }, {
      "firstName": "Elliotte", 
      "lastName": "Hunter", 
    }, {
      "firstName": "Jason", 
      "lastName": "Harold", 
    }
  ]
}

You would use the path "programmers.#.lastName" like such:

value := gjson::get(json, "programmers.#.lastName");
for name in value.array() {
	println!("{}", name);
}

You can also query an object inside an array:

let name = gjson::get(json, "programmers.#(lastName=Hunter).firstName");
println!("{}", name)  // prints "Elliotte"

Iterate through an object or array

The ForEach function allows for quickly iterating through an object or array. The key and value are passed to the iterator function for objects. Only the value is passed for arrays. Returning false from an iterator will stop iteration.

let value := gjson::get(json, "programmers")
value::each(|key, value| {
	println!("{}", value);
	true // keep iterating
});

Simple Parse and Get

There's a gjson::parse(json) function that will do a simple parse, and value.get(path) that will search a value.

For example, all of these will return the same value:

gjson::parse(json).get("name").get("last");
gjson::get(json, "name").get("last");
gjson::get(json, "name.last");

Check for the existence of a value

Sometimes you just want to know if a value exists.

let value = gjson::get(json, "name.last");
if !value.exists() {
	println!("no last name");
} else {
	println!("{}", value);
}

// Or as one step
if gjson::get(json, "name.last").exists() {
	println!("has a last name");
}

Validate JSON

The Get* and Parse* functions expects that the json is valid. Bad json will not panic, but it may return back unexpected values.

If you are consuming JSON from an unpredictable source then you may want to validate prior to using GJSON.

if !gjson::valid(json) {
	return Err("invalid json");
}
let value = gjson::get(json, "name.last");
You might also like...
A JSON Query Language CLI tool built with Rust 🦀

JQL A JSON Query Language CLI tool built with Rust 🦀 📜 Core philosophy 📦 Stay lightweight 🎮 Keep its features as simple as possible 🧠 Avoid redun

rurl is like curl but with a json configuration file per request

rurl rurl is a curl-like cli tool made in rust, the difference is that it takes its params from a json file so you can have all different requests sav

A tool for outputs semantic difference of json

jsondiff A tool for outputs semantic difference of json. "semantic" means: sort object key before comparison sort array before comparison (optional, b

Easily create dynamic css using json notation

jss! This crate provides an easy way to write dynamic css using json notation. This gives you more convenient than you think. Considering using a dyna

Decode Metaplex mint account metadata into a JSON file.

Simple Metaplex Decoder (WIP) Install From Source Install Rust. curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh Clone the source: git c

A fast and simple command-line tool for common operations over JSON-lines files

rjp: Rapid JSON-lines processor A fast and simple command-line tool for common operations over JSON-lines files, such as: converting to and from text

A node package based on jsonschema-rs for performing JSON schema validation

A node package based on jsonschema-rs for performing JSON schema validation.

Tools for working with Twitter JSON data

Twitter stream user info extractor This project lets you parse JSON data from the Twitter API or other sources to extract some basic user information,

A fast way to minify JSON

COMPACTO (work in progress) A fast way to minify JSON. Usage/Examples # Compress # Input example (~0.11 KB) # { # "id": "123", # "name": "Edua

Comments
  • add get_bytes

    add get_bytes

    This is a simplified version of #4 which only adds the new get_bytes function for when one has a &[u8] instead of an &str to avoid the need for a type conversation to a string.

    @tidwall I'm hoping you might be able merge and cut a release for this small change and then have all the time to review the other PR you need. The new get_bytes function is really the only change I require at this time, the rest is minor optimizations. I did fork this repo however, am not able to release my crate without publishing it as a separate crate which is undesirable.

    If not please let me know and I'll instead copy json into my codebase for the time being.

    opened by deankarn 6
  • plans for adding update functionality?

    plans for adding update functionality?

    We recently integrated gjson into nushell via plugin. We were wondering if there were plans on providing the functionality to update based on a query string using gjson. Maybe that already exists and I missed it?

    opened by fdncred 2
  • Literal support?

    Literal support?

    Hi,

    contrary to the Go implementation, this version doesn't seem to implement the literal notation.

    const JSON: &str = r#"{"name":{"first":"Janet","last":"Prichard"},"age":47}"#;
    
    fn main() {
        let value = gjson::get(JSON, r#"{name.first,abc:!"abc"}"#);
        println!("{}", value); // Expected {"first":"Janet", "abc": "abc"}
    }
    

    Whereas it's

        Finished dev [unoptimized + debuginfo] target(s) in 0.00s
         Running `target/debug/h`
        {"first":"Janet"}
    

    Are there any plans? Or am I doing something wrong?

    opened by celaus 3
  • Support get_bytes

    Support get_bytes

    The main goal of this PR was to add a new function gjson::get_bytes(...) to compliment the gjson::get(...) preventing the need to convert to a string, but noticed a few other things while doing that so the highlights are:

    • Added gjson::get_bytes(...) to compliment the gjson::get(...) here
    • Simplified and reduced size of Value by using Cow combining the slice and owned fields into one and deferring escaping strings until needed/used, see here
    • Converted a bunch of functions that accepted a &str and then immediately called as_bytes() on that string to accept a &[u8] directly which has reduced the need to convert between these types as well as returning Vec<u8> instead of String to help facilitate. See here for example.
    • Cleaned up some checks to be more idiomatic rust eg. !data.is_empty() vs data.len() > 0 for readability.

    These changes, for a project I'm using gjson in, benchmarked 5-10% faster in some situations when fetching values.

    opened by deankarn 3
Owner
Josh Baker
Josh Baker
Rust port of gjson,get JSON value by dotpath syntax

A-JSON Read JSON values quickly - Rust JSON Parser change name to AJSON, see issue Inspiration comes from gjson in golang Installation Add it to your

Chen Jiaju 90 Dec 6, 2022
This library is a pull parser for CommonMark, written in Rust

This library is a pull parser for CommonMark, written in Rust. It comes with a simple command-line tool, useful for rendering to HTML, and is also designed to be easy to use from as a library.

Raph Levien 1.5k Jan 1, 2023
A json5 parser for luajit

Json5 parser for luajit This crate provides json5 deserialization for luajit. Inspired and adapted from json5-rs NOTE: When compiling for macos, pleas

Joaquín León 12 Nov 19, 2022
Strongly typed JSON library for Rust

Serde JSON   Serde is a framework for serializing and deserializing Rust data structures efficiently and generically. [dependencies] serde_json = "1.0

null 3.6k Jan 5, 2023
JSON implementation in Rust

json-rust Parse and serialize JSON with ease. Changelog - Complete Documentation - Cargo - Repository Why? JSON is a very loose format where anything

Maciej Hirsz 500 Dec 21, 2022
A rust script to convert a better bibtex json file from Zotero into nice organised notes in Obsidian

Zotero to Obsidian script This is a script that takes a better bibtex JSON file exported by Zotero and generates an organised collection of reference

Sashin Exists 3 Oct 9, 2022
CLI tool to convert HOCON into valid JSON or YAML written in Rust.

{hocon:vert} CLI Tool to convert HOCON into valid JSON or YAML. Under normal circumstances this is mostly not needed because hocon configs are parsed

Mathias Oertel 23 Jan 6, 2023
Typify - Compile JSON Schema documents into Rust types.

Typify Compile JSON Schema documents into Rust types. This can be used ... via the macro import_types!("types.json") to generate Rust types directly i

Oxide Computer Company 73 Dec 27, 2022
A easy and declarative way to test JSON input in Rust.

assert_json A easy and declarative way to test JSON input in Rust. assert_json is a Rust macro heavily inspired by serde json macro. Instead of creati

Charles Vandevoorde 8 Dec 5, 2022
A small rust database that uses json in memory.

Tiny Query Database (TQDB) TQDB is a small library for creating a query-able database that is encoded with json. The library is well tested (~96.30% c

Kace Cottam 2 Jan 4, 2022