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-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-04-13 22:27:33 +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` also.
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-04-09 18:43:56 +09:00
- [jsonpath_lib crate ](#jsonpath_lib-crate )
2019-04-09 13:18:00 +09:00
- [Rust - jsonpath::Selector struct ](#rust---jsonpathselector-struct )
- [Rust - jsonpath::select(json: &serde_json::value::Value, jsonpath: &str) ](#rust---jsonpathselectjson-serde_jsonvaluevalue-jsonpath-str )
- [Rust - jsonpath::select_as_str(json_str: &str, jsonpath: &str) ](#rust---jsonpathselect_as_strjson-str-jsonpath-str )
- [Rust - jsonpath::select_as\<T: `serde::de::DeserializeOwned`\>(json_str: &str, jsonpath: &str) ](#rust---jsonpathselect_ast-serdededeserializeownedjson-str-jsonpath-str )
- [Rust - jsonpath::compile(jsonpath: &str) ](#rust---jsonpathcompilejsonpath-str )
- [Rust - jsonpath::selector(json: &serde_json::value::Value) ](#rust---jsonpathselectorjson-serde_jsonvaluevalue )
- [Rust - jsonpath::selector_as\<T: `serde::de::DeserializeOwned`\>(json: &serde_json::value::Value) ](#rust---jsonpathselector_ast-serdededeserializeownedjson-serde_jsonvaluevalue )
2019-04-13 22:27:33 +09:00
- [Rust - Other Examples ](https://github.com/freestrings/jsonpath/wiki/rust-examples )
2019-03-06 23:50:10 +09:00
2019-04-09 18:43:56 +09:00
## Javascript API
2019-03-06 18:55:21 +09:00
2019-04-09 18:43:56 +09:00
- [npm package ](#npm-package )
- [Javascript - jsonpath.Selector class ](#javascript---selector-class )
- [Javascript - jsonpath.select(json: string|object, jsonpath: string) ](#javascript---jsonpathselectjson-stringobject-jsonpath-string )
- [Javascript - jsonpath.compile(jsonpath: string) ](#javascript---jsonpathcompilejsonpath-string )
- [Javascript - jsonpath.selector(json: string|object) ](#javascript---jsonpathselectorjson-stringobject )
- [Javascript - allocJson, deallocJson (Webassembly Only) ](#javascript---allocjson-deallocjson-webassembly-only )
2019-04-13 22:27:33 +09:00
- [Javascript - Other Examples ](https://github.com/freestrings/jsonpath/wiki/Javascript-examples )
2019-03-11 17:35:15 +09:00
2019-04-09 18:43:56 +09:00
---
2019-04-05 11:52:20 +09:00
2019-04-09 18:43:56 +09:00
### Rust API
2019-03-11 17:35:15 +09:00
2019-04-09 18:43:56 +09:00
#### jsonpath_lib crate
[Go to 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;
#[macro_use]
extern crate serde_json;
```
2019-04-09 18:43:56 +09:00
#### Rust - jsonpath::Selector struct
2019-04-08 14:44:18 +09:00
```rust
#[derive(Serialize, Deserialize, PartialEq, Debug)]
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()
// .value_from_str(& serde_json::to_string(& json_obj).unwrap() /*& str*/).unwrap()
// .value_from(& json_obj /*& impl serde::ser::Serialize*/).unwrap()
2019-05-06 22:29:28 +09:00
.value(& json_obj /*serde_json::value::Value*/ ).unwrap()
2019-04-08 14:44:18 +09:00
.select_to_value().unwrap();
assert_eq!(json!([{"name": "친구3", "age": 30}]), result);
let result = selector.select_to_str().unwrap();
assert_eq!(r#"[{"name":"친구3","age":30}]"#, result);
let result = selector.select_to::< Vec < Friend > >().unwrap();
assert_eq!(vec![Friend { name: "친구3".to_string(), age: Some(30) }], result);
```
2019-04-09 18:43:56 +09:00
#### Rust - jsonpath::select(json: &serde_json::value::Value, jsonpath: &str)
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();
let ret = json!([
{"name": "친구3", "age": 30},
{"name": "친구1", "age": 20}
]);
assert_eq!(json, ret);
2019-03-06 18:55:21 +09:00
```
2019-04-09 18:43:56 +09:00
#### Rust - jsonpath::select_as_str(json: &str, jsonpath: &str)
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-04-09 18:43:56 +09:00
#### Rust - jsonpath::select_as\<T: `serde::de::DeserializeOwned`\>(json: &str, jsonpath: &str)
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-03-24 21:18:58 +09:00
let ret: Person = jsonpath::select_as(r#"
{
"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-03-24 21:18:58 +09:00
assert_eq!(person, ret);
```
2019-04-09 18:43:56 +09:00
#### Rust - jsonpath::compile(jsonpath: &str)
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
let ret = json!([
{"name": "친구3", "age": 30},
{"name": "친구1", "age": 20}
]);
2019-03-06 18:55:21 +09:00
assert_eq!(json, ret);
2019-04-04 09:37:44 +09:00
```
2019-04-09 18:43:56 +09:00
#### Rust - jsonpath::selector(json: &serde_json::value::Value)
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();
let ret = json!([
{"name": "친구3", "age": 30},
{"name": "친구1", "age": 20}
]);
assert_eq!(json, ret);
let json = selector("$..friends[1]").unwrap();
let ret = json!([
{"name": "친구4"},
{"name": "친구2", "age": 20}
]);
2019-03-06 18:55:21 +09:00
assert_eq!(json, ret);
```
2019-04-09 18:43:56 +09:00
#### Rust - jsonpath::selector_as\<T: `serde::de::DeserializeOwned`\>(json: &serde_json::value::Value)
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-04-04 09:37:44 +09:00
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Friend {
name: String,
age: Option< u8 > ,
}
let mut selector = jsonpath::selector_as::< Vec < 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
```
---
### Javascript API
#### npm package
2019-04-13 22:27:33 +09:00
##### 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)
[Goto npmjs.org ](https://www.npmjs.com/package/jsonpath-rs )
```javascript
const jsonpath = require('jsonpath-rs');
```
#### javascript - Selector class
##### 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);
let selectToObj = selector.selectTo();
let selectToString = selector.selectToStr();
console.log(
JSON.stringify(ret) == JSON.stringify(selectToObj),
JSON.stringify(ret) == selectToString
);
// => true, true
```
##### 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);
let selectToObj = selector.selectTo();
let selectToString = selector.selectToStr();
console.log(
JSON.stringify(ret) == JSON.stringify(selectToObj),
JSON.stringify(ret) == selectToString
);
// => true, true
```
#### Javascript - jsonpath.select(json: string|object, jsonpath: string)
```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
```
#### Javascript - jsonpath.compile(jsonpath: string)
```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
```
#### Javascript - jsonpath.selector(json: string|object)
```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
```
#### Javascript - allocJson, deallocJson (Webassembly Only)
wasm-bindgen은 Javascript와 Webassembly간 값을 주고받을 때 JSON 객체는 String으로 변환되기 때문에, 반복해서 사용되는 JSON 객체는 Webassembly 영역에 생성해 두면 성능에 도움이 된다.
Since wasm-bindgen converts JSON objects to String when exchanging values between Javascript and Webassembly, creating frequently used JSON objects in the WebAssembly area helps performance.
```javascript
2019-04-13 22:27:33 +09:00
const jsonpath = require('jsonpath-wasm');
2019-04-09 18:43:56 +09:00
let jsonObj = {
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]
};
// allocate jsonObj in webassembly
let ptr = jsonpath.allocJson(jsonObj);
// `0` is invalid pointer
if(ptr == 0) {
console.error('invalid ptr');
}
let path = '$..friends[0]';
let template = jsonpath.compile(path);
let selector = jsonpath.selector(jsonObj);
// create selector as pointer
let ptrSelector = jsonpath.selector(ptr);
let ret1 = selector(path)
let ret2 = ptrSelector(path)
let ret3 = template(jsonObj);
// select as pointer
let ret4 = template(ptr);
let ret5 = jsonpath.select(jsonObj, path);
// select as pointer
let ret6 = jsonpath.select(ptr, path);
console.log(
JSON.stringify(ret1) == JSON.stringify(ret2),
JSON.stringify(ret1) == JSON.stringify(ret3),
JSON.stringify(ret1) == JSON.stringify(ret4),
JSON.stringify(ret1) == JSON.stringify(ret5),
JSON.stringify(ret1) == JSON.stringify(ret6));
// => true true true true true
jsonpath.deallocJson(ptr);
```