2019-03-29 12:15:07 +09:00
# jsonpath_lib
2018-12-26 14:45:31 +09:00
2019-03-06 23:50:10 +09:00
[](https://travis-ci.org/freestrings/jsonpath)
2019-03-11 17:35:15 +09:00

2019-04-10 18:04:38 +09:00

2019-04-13 22:27:33 +09:00

2019-06-20 21:27:06 +09:00

2019-03-06 23:50:10 +09:00
2019-04-09 13:18:00 +09:00
`Rust` 버전 [JsonPath ](https://goessner.net/articles/JsonPath/ ) 구현이다. `Webassembly` 와 `Javascript` 에서도 유사한 API 인터페이스를 제공 한다.
2019-03-06 23:50:10 +09:00
2019-06-24 14:20:29 +09:00
It is JsonPath [JsonPath ](https://goessner.net/articles/JsonPath/ ) engine written in `Rust` . it provide a similar API interface in `Webassembly` and` Javascript` too.
2018-12-26 14:45:31 +09:00
2019-03-23 11:51:35 +09:00
- [Webassembly Demo ](https://freestrings.github.io/jsonpath/ )
2019-04-13 22:27:33 +09:00
- [NPM jsonpath-wasm - webassembly ](https://www.npmjs.com/package/jsonpath-wasm )
- [NPM jsonpath-rs - native addon ](https://www.npmjs.com/package/jsonpath-rs )
2019-03-06 23:50:10 +09:00
2019-04-09 18:43:56 +09:00
## Rust API
2019-03-06 23:50:10 +09:00
2019-06-11 12:14:12 +09:00
< details > < summary > < b > jsonpath_lib crate< / b > < / summary >
2019-03-06 23:50:10 +09:00
2019-06-11 12:14:12 +09:00
Go to [`jsonpath_lib` creates.io ](https://crates.io/crates/jsonpath_lib )
2019-03-06 23:50:10 +09:00
2019-03-06 18:55:21 +09:00
```rust
extern crate jsonpath_lib as jsonpath;
```
2019-06-11 12:14:12 +09:00
< / details >
< details > < summary > < b > Rust - jsonpath::Selector struct< / b > < / summary >
2019-04-08 14:44:18 +09:00
```rust
2019-06-03 13:50:44 +09:00
#[derive(Deserialize, PartialEq, Debug)]
2019-04-08 14:44:18 +09:00
struct Friend {
name: String,
age: Option< u8 > ,
}
let json_obj = json!({
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]});
let mut selector = Selector::new();
let result = selector
.path("$..[?(@.age >= 30)]").unwrap()
2019-06-03 13:50:44 +09:00
.value(& json_obj)
.select().unwrap();
2019-04-08 14:44:18 +09:00
2019-06-03 13:50:44 +09:00
assert_eq!(vec![& json!({"name": "친구3", "age": 30})], result);
2019-04-08 14:44:18 +09:00
2019-05-15 18:19:00 +09:00
let result = selector.select_as_str().unwrap();
2019-04-08 14:44:18 +09:00
assert_eq!(r#"[{"name":"친구3","age":30}]"#, result);
2019-06-03 13:50:44 +09:00
let result = selector.select_as::< Friend > ().unwrap();
2019-04-08 14:44:18 +09:00
assert_eq!(vec![Friend { name: "친구3".to_string(), age: Some(30) }], result);
```
2019-06-11 12:14:12 +09:00
< / details >
< details > < summary > < b > Rust - jsonpath::SelectorMut struct< / b > < / summary >
2019-06-10 14:48:29 +09:00
```rust
let json_obj = json!({
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]});
let mut selector_mut = SelectorMut::new();
let result = selector_mut
.str_path("$..[?(@.age == 20)].age").unwrap()
.value(json_obj)
.replace_with(& mut |v| {
let age = if let Value::Number(n) = v {
n.as_u64().unwrap() * 2
} else {
0
};
json!(age)
}).unwrap()
.take().unwrap();
assert_eq!(result, json!({
"school": {
"friends": [
{"name": "친구1", "age": 40},
{"name": "친구2", "age": 40}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]}));
```
2019-06-11 12:14:12 +09:00
< / details >
< details > < summary > < b > Rust - jsonpath::select(json: & serde_json::value::Value, jsonpath: & str)< / b > < / summary >
2019-03-06 18:55:21 +09:00
```rust
let json_obj = json!({
"school": {
2019-04-04 09:37:44 +09:00
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
2019-03-06 18:55:21 +09:00
},
2019-04-04 09:37:44 +09:00
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]});
let json = jsonpath::select(& json_obj, "$..friends[0]").unwrap();
2019-06-03 13:50:44 +09:00
assert_eq!(json, vec![
& json!({"name": "친구3", "age": 30}),
& json!({"name": "친구1", "age": 20})
2019-04-04 09:37:44 +09:00
]);
2019-03-06 18:55:21 +09:00
```
2019-06-11 12:14:12 +09:00
< / details >
< details > < summary > < b > Rust - jsonpath::select_as_str(json_str: & str, jsonpath: & str)< / b > < / summary >
2019-03-18 10:59:08 +09:00
```rust
2019-04-04 09:37:44 +09:00
let ret = jsonpath::select_as_str(r#"
{
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]
}
"#, "$..friends[0]").unwrap();
assert_eq!(ret, r#"[{"name":"친구3","age":30},{"name":"친구1","age":20}]"#);
2019-03-18 10:59:08 +09:00
```
2019-06-11 12:14:12 +09:00
< / details >
< details >< summary >< b > Rust - jsonpath::select_as< T: `serde::de::DeserializeOwned` > (json_str: & str, jsonpath: & str)</ b ></ summary >
2019-03-24 21:18:58 +09:00
```rust
2019-04-04 09:37:44 +09:00
#[derive(Deserialize, PartialEq, Debug)]
2019-03-24 21:18:58 +09:00
struct Person {
name: String,
age: u8,
phones: Vec< String > ,
}
2019-04-04 09:37:44 +09:00
2019-06-03 13:50:44 +09:00
let ret: Vec< Person > = jsonpath::select_as(r#"
2019-03-24 21:18:58 +09:00
{
"person":
{
"name": "Doe John",
"age": 44,
"phones": [
"+44 1234567",
"+44 2345678"
]
}
}
"#, "$.person").unwrap();
2019-04-04 09:37:44 +09:00
2019-03-24 21:18:58 +09:00
let person = Person {
name: "Doe John".to_string(),
age: 44,
phones: vec!["+44 1234567".to_string(), "+44 2345678".to_string()],
};
2019-04-04 09:37:44 +09:00
2019-06-03 13:50:44 +09:00
assert_eq!(ret[0], person);
2019-03-24 21:18:58 +09:00
```
2019-06-11 12:14:12 +09:00
< / details >
< details > < summary > < b > Rust - jsonpath::compile(jsonpath: & str)< / b > < / summary >
2019-03-06 18:55:21 +09:00
```rust
let mut template = jsonpath::compile("$..friends[0]");
let json_obj = json!({
"school": {
2019-04-04 09:37:44 +09:00
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
2019-03-06 18:55:21 +09:00
},
2019-04-04 09:37:44 +09:00
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]});
2019-03-06 18:55:21 +09:00
2019-03-17 18:25:00 +09:00
let json = template(&json_obj).unwrap();
2019-04-04 09:37:44 +09:00
2019-06-03 13:50:44 +09:00
assert_eq!(json, vec![
& json!({"name": "친구3", "age": 30}),
& json!({"name": "친구1", "age": 20})
2019-04-04 09:37:44 +09:00
]);
```
2019-06-11 12:14:12 +09:00
< / details >
< details > < summary > < b > Rust - jsonpath::selector(json: & serde_json::value::Value)< / b > < / summary >
2019-03-06 18:55:21 +09:00
2019-04-04 09:37:44 +09:00
```rust
2019-03-06 18:55:21 +09:00
let json_obj = json!({
"school": {
2019-04-04 09:37:44 +09:00
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
2019-03-06 18:55:21 +09:00
},
2019-04-04 09:37:44 +09:00
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]});
let mut selector = jsonpath::selector(&json_obj);
let json = selector("$..friends[0]").unwrap();
2019-06-03 13:50:44 +09:00
assert_eq!(json, vec![
& json!({"name": "친구3", "age": 30}),
& json!({"name": "친구1", "age": 20})
2019-04-04 09:37:44 +09:00
]);
let json = selector("$..friends[1]").unwrap();
2019-06-03 13:50:44 +09:00
assert_eq!(json, vec![
& json!({"name": "친구4"}),
& json!({"name": "친구2", "age": 20})
2019-04-04 09:37:44 +09:00
]);
2019-03-06 18:55:21 +09:00
```
2019-06-11 12:14:12 +09:00
< / details >
< details > < summary > < b > Rust - jsonpath::selector_as< T: serde::de::DeserializeOwned> (json: & serde_json::value::Value)< / b > < / summary >
2019-03-06 18:55:21 +09:00
```rust
let json_obj = json!({
"school": {
2019-04-04 09:37:44 +09:00
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
2019-03-06 18:55:21 +09:00
},
2019-04-04 09:37:44 +09:00
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]});
2019-03-06 18:55:21 +09:00
2019-06-03 13:50:44 +09:00
#[derive(Deserialize, PartialEq, Debug)]
2019-04-04 09:37:44 +09:00
struct Friend {
name: String,
age: Option< u8 > ,
}
2019-06-03 13:50:44 +09:00
let mut selector = jsonpath::selector_as::< Friend > (&json_obj);
2019-03-06 18:55:21 +09:00
2019-03-11 17:35:15 +09:00
let json = selector("$..friends[0]").unwrap();
2019-04-04 09:37:44 +09:00
let ret = vec!(
Friend { name: "친구3".to_string(), age: Some(30) },
Friend { name: "친구1".to_string(), age: Some(20) }
);
2019-03-06 18:55:21 +09:00
assert_eq!(json, ret);
2019-03-11 17:35:15 +09:00
let json = selector("$..friends[1]").unwrap();
2019-04-04 09:37:44 +09:00
let ret = vec!(
Friend { name: "친구4".to_string(), age: None },
Friend { name: "친구2".to_string(), age: Some(20) }
);
2019-03-06 18:55:21 +09:00
assert_eq!(json, ret);
2019-04-09 18:43:56 +09:00
```
2019-06-11 12:14:12 +09:00
< / details >
< details > < summary > < b > Rust - jsonpath::delete(value: & Value, path: & str)< / b > < / summary >
2019-06-10 14:48:29 +09:00
```rust
let json_obj = json!({
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]});
let ret = jsonpath::delete(json_obj, "$..[?(20 == @.age)]").unwrap();
assert_eq!(ret, json!({
"school": {
"friends": [
null,
null
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]}));
```
2019-06-11 12:14:12 +09:00
< / details >
< details > < summary > < b > Rust - jsonpath::replace_with< F: FnMut(& Value) -> Value> (value: & Value, path: & str, fun: & mut F)< / b > < / summary >
2019-06-10 14:48:29 +09:00
```rust
let json_obj = json!({
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]});
let ret = jsonpath::replace_with(json_obj, "$..[?(@.age == 20)].age", & mut |v| {
let age = if let Value::Number(n) = v {
n.as_u64().unwrap() * 2
} else {
0
};
json!(age)
}).unwrap();
assert_eq!(ret, json!({
"school": {
"friends": [
{"name": "친구1", "age": 40},
{"name": "친구2", "age": 40}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]}));
```
2019-04-09 18:43:56 +09:00
2019-06-11 12:14:12 +09:00
< / details >
2019-04-09 18:43:56 +09:00
2019-06-11 12:14:12 +09:00
[Rust - Other Examples ](https://github.com/freestrings/jsonpath/wiki/rust-examples )
## Javascript API
< details > < summary > < b > npm package< / b > < / summary >
2019-04-09 18:43:56 +09:00
2019-04-13 22:27:33 +09:00
##### jsonpath-wasm
2019-04-09 18:43:56 +09:00
2019-06-11 12:14:12 +09:00
Goto [`jsonpath-wasm` npmjs.org ](https://www.npmjs.com/package/jsonpath-wasm )
2019-04-09 18:43:56 +09:00
```javascript
// browser
import * as jsonpath from "jsonpath-wasm";
// NodeJs
const jsonpath = require('jsonpath-wasm');
```
##### jsonpath-rs (NodeJS only)
2019-06-11 12:14:12 +09:00
Goto [`jsonpath-rs` npmjs.org ](https://www.npmjs.com/package/jsonpath-rs )
2019-04-09 18:43:56 +09:00
```javascript
const jsonpath = require('jsonpath-rs');
```
2019-06-11 12:14:12 +09:00
< / details >
< details > < summary > < b > Javascript - jsonpath.Selector class< / b > < / summary >
2019-04-09 18:43:56 +09:00
##### jsonpath-wasm
2019-04-13 22:27:33 +09:00
`wasm-bindgen` 리턴 타입 제약 때문에 빌더 패턴은 지원하지 않는다.
2019-04-09 18:43:56 +09:00
It does not support `builder-pattern` due to the `return type` restriction of `wasm-bindgen` .
```javascript
let jsonObj = {
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]
};
let ret = [
{"name": "친구3", "age": 30},
{"name": "친구1", "age": 20}
];
let selector = new jsonpath.Selector();
selector.path('$..friends[0]');
selector.value(jsonObj);
2019-06-03 13:50:44 +09:00
let retObj = selector.select();
2019-04-09 18:43:56 +09:00
2019-06-03 13:50:44 +09:00
console.log(JSON.stringify(ret) == JSON.stringify(retObj));
2019-05-15 18:19:00 +09:00
// => true
2019-04-09 18:43:56 +09:00
```
##### jsonpath-rs
```javascript
let jsonObj = {
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]
};
let ret = [
{"name": "친구3", "age": 30},
{"name": "친구1", "age": 20}
];
let selector = new jsonpath.Selector()
.path('$..friends[0]')
.value(jsonObj);
2019-06-03 13:50:44 +09:00
let retObj = selector.select();
2019-04-09 18:43:56 +09:00
2019-06-03 13:50:44 +09:00
console.log(JSON.stringify(ret) == JSON.stringify(retObj));
2019-04-09 18:43:56 +09:00
2019-06-03 13:50:44 +09:00
// => true
2019-04-09 18:43:56 +09:00
```
2019-06-11 12:14:12 +09:00
< / details >
< details > < summary > < b > Javascript - jsonpath.SelectorMut class< / b > < / summary >
빌더 패턴 제약은 `Selector class` 와 동일하다.
```javascript
let jsonObj = {
'school': {
'friends': [
{'name': '친구1', 'age': 20},
{'name': '친구2', 'age': 20},
],
},
'friends': [
{'name': '친구3', 'age': 30},
{'name': '친구4'},
],
};
let selector = new jsonpath.SelectorMut();
selector.path('$..[?(@.age == 20)]');
{
selector.value(jsonObj);
selector.deleteValue();
let resultObj = {
'school': {'friends': [null, null]},
'friends': [
{'name': '친구3', 'age': 30},
{'name': '친구4'},
],
};
console.log(JSON.stringify(selector.take()) !== JSON.stringify(resultObj));
// => true
}
{
selector.value(jsonObj);
selector.replaceWith((v) => {
v.age = v.age * 2;
return v;
});
let resultObj = {
'school': {
'friends': [
{'name': '친구1', 'age': 40},
{'name': '친구2', 'age': 40},
],
},
'friends': [
{'name': '친구3', 'age': 30},
{'name': '친구4'},
],
};
console.log(JSON.stringify(selector.take()) !== JSON.stringify(resultObj));
// => true
}
```
< / details >
< details > < summary > < b > Javascript - jsonpath.select(json: string|object, jsonpath: string)< / b > < / summary >
2019-04-09 18:43:56 +09:00
```javascript
let jsonObj = {
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]
};
let ret = [
{"name": "친구3", "age": 30},
{"name": "친구1", "age": 20}
];
let selectAsString = jsonpath.select(JSON.stringify(jsonObj), '$..friends[0]');
let selectAsObj = jsonpath.select(jsonObj, '$..friends[0]');
console.log(
JSON.stringify(ret) == JSON.stringify(selectAsString),
JSON.stringify(ret) == JSON.stringify(selectAsObj)
);
// => true, true
```
2019-06-11 12:14:12 +09:00
< / details >
< details > < summary > < b > Javascript - jsonpath.compile(jsonpath: string)< / b > < / summary >
2019-04-09 18:43:56 +09:00
```javascript
let template = jsonpath.compile('$..friends[0]');
let jsonObj = {
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]
};
let ret = [
{"name": "친구3", "age": 30},
{"name": "친구1", "age": 20}
];
let selectAsString = template(JSON.stringify(jsonObj));
let selectAsObj = template(jsonObj);
console.log(
JSON.stringify(ret) == JSON.stringify(selectAsString),
JSON.stringify(ret) == JSON.stringify(selectAsObj)
);
// => true, true
let jsonObj2 = {
"school": {
"friends": [
{"name": "Millicent Norman"},
{"name": "Vincent Cannon"}
]
},
"friends": [ {"age": 30}, {"age": 40} ]
};
let ret2 = [
{"age": 30},
{"name": "Millicent Norman"}
];
let selectAsString2 = template(JSON.stringify(jsonObj2));
let selectAsObj2 = template(jsonObj2);
console.log(
JSON.stringify(ret2) == JSON.stringify(selectAsString2),
JSON.stringify(ret2) == JSON.stringify(selectAsObj2)
);
// => true, true
```
2019-06-11 12:14:12 +09:00
< / details >
< details > < summary > < b > Javascript - jsonpath.selector(json: string|object)< / b > < / summary >
2019-04-09 18:43:56 +09:00
```javascript
let jsonObj = {
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]
};
let ret1 = [
{"name": "친구3", "age": 30},
{"name": "친구1", "age": 20}
];
let ret2 = [
{"name": "친구4"},
{"name": "친구2", "age": 20}
];
let selector = jsonpath.selector(jsonObj);
// or as json string
// let selector = jsonpath.selector(JSON.stringify(jsonObj));
let select1 = selector('$..friends[0]');
let select2 = selector('$..friends[1]');
console.log(
JSON.stringify(ret1) == JSON.stringify(select1),
JSON.stringify(ret2) == JSON.stringify(select2)
);
// => true, true
2019-06-11 12:14:12 +09:00
```
< / details >
< details > < summary > < b > Javascript - jsonpath.deleteValue(json: string|object, path: string)< / b > < / summary >
```javascript
let jsonObj = {
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]
};
let _1 = jsonpath.deleteValue(jsonObj, '$..friends[0]');
let result = jsonpath.deleteValue(_1, '$..friends[1]');
console.log(JSON.stringify(result) !== JSON.stringify({
"school": { "friends": [null, null]},
"friends": [null, null]
}));
// => true
```
< / details >
< details > < summary > < b > Javascript - jsonpath.replaceWith(json: string|object, path: string, fun: function(json: object) => json: object< / b > < / summary >
```javascript
let jsonObj = {
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]
};
let result = jsonpath.replaceWith(jsonObj, '$..friends[0]', (v) => {
v.age = v.age * 2;
return v;
});
console.log(JSON.stringify(result) === JSON.stringify({
"school": {
"friends": [
{"name": "친구1", "age": 40},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 60},
{"name": "친구4"}
]
}));
// => true
```
< / details >
[Javascript - Other Examples ](https://github.com/freestrings/jsonpath/wiki/Javascript-examples )