rust-ajson
rust-ajson copied to clipboard
Rust port of gjson,get JSON value by dotpath syntax
change name to AJSON, see issue
Inspiration comes from gjson in golang
Installation
Add it to your Cargo.toml file:
[dependencies]
ajson = "0.3"
Todo
- Add documentation
- Follow api-guidelines
- Update benchmark
- Optimize
A simple example
AJSON get json value with specified path, such as project.name or project.version. When the path matches, it returns immediately!
let data = r#"
{
"project": {
"name": "ajson",
"maintainer": "importcjj",
"version": 0.1,
"rusts": ["stable", "nightly"]
}
}
"#;
let name = ajson::get(data, "project.name").unwrap().unwrap();
println!("{}", name.as_str()); // ajson
Path Syntax
JSON example
{
"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"]}
]
}
basic
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.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"
Escape character
Special purpose characters, such as ., *, and ? can be escaped with .
fav\.movie "Deer Hunter"
Arrays
The # character allows for digging into JSON Arrays.To get the length of an array you'll just use the # all by itself.
friends.# 3
friends.#.age [44,68,47]
queries
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.#(nets.#(=="fb"))#.first >> ["Dale","Roger"]
construct
Basically, you can use selectors to assemble whatever you want, and of course, the result is still a json ;)
{name.first,age,"murphys":friends.#(last="Murphy")#.first}
[name.first,age,children.0]
ajson::get(json, "name.[first,last]").unwrap().unwrap().to_vec();
ajson::get(json, "name.first").unwrap().unwrap();
ajson::get(json, "name.last").unwrap().unwrap();
Value
Value types.
enum Value {
String(String),
Number(Number),
Object(String),
Array(String),
Boolean(bool),
Null,
}
Value has a number of methods that meet your different needs.
value.get(&str) -> Option<Value>
value.as_str() -> &str
value.as_u64() -> u64
value.as_i64() -> i64
value.as_f64() -> f64
value.as_bool() -> bool
value.as_vec() -> Vec<Value>
value.as_object() -> HashMap<String, Value>
value.is_number() -> bool
value.is_string() -> bool
value.is_bool() -> bool
value.is_object() -> bool
value.is_array() -> bool
value.is_null() -> bool
Performance
$ cargo bench
ajson benchmark time: [2.0816 us 2.0865 us 2.0917 us]
change: [+0.6172% +0.9272% +1.2430%] (p = 0.00 < 0.05)
Change within noise threshold.
Found 11 outliers among 100 measurements (11.00%)
7 (7.00%) high mild
4 (4.00%) high severe
serde_json benchmark time: [23.033 us 23.076 us 23.119 us]
change: [-0.7185% -0.3455% +0.0230%] (p = 0.07 > 0.05)
No change in performance detected.
Found 7 outliers among 100 measurements (7.00%)
6 (6.00%) high mild
1 (1.00%) high severe
json-rust benchmark time: [12.225 us 12.289 us 12.381 us]
change: [-2.6200% -1.1789% +0.8442%] (p = 0.19 > 0.05)
No change in performance detected.
Found 9 outliers among 100 measurements (9.00%)
5 (5.00%) high mild
4 (4.00%) high severe
ajson selector time: [1.1523 us 1.1561 us 1.1604 us]
change: [+0.1567% +0.7278% +1.2945%] (p = 0.01 < 0.05)
Change within noise threshold.
Found 3 outliers among 100 measurements (3.00%)
3 (3.00%) high mild
ajson multi query time: [559.19 ns 559.96 ns 560.77 ns]
change: [-1.4268% -1.0380% -0.6698%] (p = 0.00 < 0.05)
Change within noise threshold.
Found 3 outliers among 100 measurements (3.00%)
3 (3.00%) high mild
serde derive time: [4.5301 us 4.5403 us 4.5507 us]
change: [-2.3423% -1.9438% -1.5697%] (p = 0.00 < 0.05)
Performance has improved.
Found 2 outliers among 100 measurements (2.00%)
2 (2.00%) high mild
serde derive multi query
time: [956.86 ns 962.64 ns 970.05 ns]
change: [-1.7069% -1.0299% -0.2924%] (p = 0.01 < 0.05)
Change within noise threshold.
Found 9 outliers among 100 measurements (9.00%)
3 (3.00%) high mild
6 (6.00%) high severe
nom json bench time: [2.9468 us 2.9515 us 2.9566 us]
Found 5 outliers among 100 measurements (5.00%)
4 (4.00%) high mild
1 (1.00%) high severe
- MacBook Pro (14-inch, 2021)
- Apple M1 Pro
- 16 GB
License
MIT License.