diff options
Diffstat (limited to 'vendor/jsonpath_lib/README.md')
-rw-r--r-- | vendor/jsonpath_lib/README.md | 698 |
1 files changed, 698 insertions, 0 deletions
diff --git a/vendor/jsonpath_lib/README.md b/vendor/jsonpath_lib/README.md new file mode 100644 index 000000000..218f1224d --- /dev/null +++ b/vendor/jsonpath_lib/README.md @@ -0,0 +1,698 @@ +# jsonpath_lib + +[![Build Status](https://travis-ci.org/freestrings/jsonpath.svg?branch=master)](https://travis-ci.org/freestrings/jsonpath) +![crates.io](https://img.shields.io/crates/v/jsonpath_lib.svg) +![npm](https://img.shields.io/npm/v/jsonpath-wasm.svg?label=npm%20%60jsonpath-wasm%60) +![Codecov](https://img.shields.io/codecov/c/github/freestrings/jsonpath.svg?token=92c41b4e7cf04a9cbebc08f68c5da615) + +`Rust` 버전 [JsonPath](https://goessner.net/articles/JsonPath/) 구현으로 `Webassembly`와 `Javascript`에서도 유사한 API 인터페이스를 제공 한다. + +It is JsonPath [JsonPath](https://goessner.net/articles/JsonPath/) engine written in `Rust`. it provide a similar API interface in `Webassembly` and` Javascript` too. + +- [Webassembly Demo](https://freestrings.github.io/jsonpath/) +- [NPM jsonpath-wasm - webassembly](https://www.npmjs.com/package/jsonpath-wasm) + +## Rust API + +<details><summary><b>jsonpath_lib crate</b></summary> + +Go to [`jsonpath_lib` creates.io](https://crates.io/crates/jsonpath_lib) + +```rust +extern crate jsonpath_lib as jsonpath; +``` + +</details> + +<details><summary><b>Rust - jsonpath::Selector struct</b></summary> + +```rust +#[derive(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(&json_obj) + .select().unwrap(); + +assert_eq!(vec![&json!({"name": "친구3", "age": 30})], result); + +let result = selector.select_as_str().unwrap(); +assert_eq!(r#"[{"name":"친구3","age":30}]"#, result); + +let result = selector.select_as::<Friend>().unwrap(); +assert_eq!(vec![Friend { name: "친구3".to_string(), age: Some(30) }], result); +``` + +</details> + +<details><summary><b>Rust - jsonpath::SelectorMut struct</b></summary> + +```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 + }; + + Some(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"} +]})); +``` + +</details> + +<details><summary><b>Rust - jsonpath::select(json: &serde_json::value::Value, jsonpath: &str)</b></summary> + +```rust +let json_obj = json!({ + "school": { + "friends": [ + {"name": "친구1", "age": 20}, + {"name": "친구2", "age": 20} + ] + }, + "friends": [ + {"name": "친구3", "age": 30}, + {"name": "친구4"} +]}); + +let json = jsonpath::select(&json_obj, "$..friends[0]").unwrap(); + +assert_eq!(json, vec![ + &json!({"name": "친구3", "age": 30}), + &json!({"name": "친구1", "age": 20}) +]); +``` + +</details> + + +<details><summary><b>Rust - jsonpath::select_as_str(json_str: &str, jsonpath: &str)</b></summary> + +```rust +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}]"#); +``` + +</details> + +<details><summary><b>Rust - jsonpath::select_as<T: `serde::de::DeserializeOwned`>(json_str: &str, jsonpath: &str)</b></summary> + +```rust +#[derive(Deserialize, PartialEq, Debug)] +struct Person { + name: String, + age: u8, + phones: Vec<String>, +} + +let ret: Vec<Person> = jsonpath::select_as(r#" +{ + "person": + { + "name": "Doe John", + "age": 44, + "phones": [ + "+44 1234567", + "+44 2345678" + ] + } +} +"#, "$.person").unwrap(); + +let person = Person { + name: "Doe John".to_string(), + age: 44, + phones: vec!["+44 1234567".to_string(), "+44 2345678".to_string()], +}; + +assert_eq!(ret[0], person); +``` + +</details> + +<details><summary><b>Rust - jsonpath::Compiled::compile(jsonpath: &str)</b></summary> + +```rust +let template = jsonpath::Compiled::compile("$..friends[0]").unwrap(); + +let json_obj = json!({ + "school": { + "friends": [ + {"name": "친구1", "age": 20}, + {"name": "친구2", "age": 20} + ] + }, + "friends": [ + {"name": "친구3", "age": 30}, + {"name": "친구4"} +]}); + +let json = template.select(&json_obj).unwrap(); + +assert_eq!(json, vec![ + &json!({"name": "친구3", "age": 30}), + &json!({"name": "친구1", "age": 20}) +]); +``` + +</details> + +<details><summary><b>Rust - jsonpath::selector(json: &serde_json::value::Value)</b></summary> + +```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 = jsonpath::selector(&json_obj); + +let json = selector("$..friends[0]").unwrap(); + +assert_eq!(json, vec![ + &json!({"name": "친구3", "age": 30}), + &json!({"name": "친구1", "age": 20}) +]); + +let json = selector("$..friends[1]").unwrap(); + +assert_eq!(json, vec![ + &json!({"name": "친구4"}), + &json!({"name": "친구2", "age": 20}) +]); +``` + +</details> + +<details><summary><b>Rust - jsonpath::selector_as<T: serde::de::DeserializeOwned>(json: &serde_json::value::Value)</b></summary> + +```rust +let json_obj = json!({ + "school": { + "friends": [ + {"name": "친구1", "age": 20}, + {"name": "친구2", "age": 20} + ] + }, + "friends": [ + {"name": "친구3", "age": 30}, + {"name": "친구4"} +]}); + +#[derive(Deserialize, PartialEq, Debug)] +struct Friend { + name: String, + age: Option<u8>, +} + +let mut selector = jsonpath::selector_as::<Friend>(&json_obj); + +let json = selector("$..friends[0]").unwrap(); + +let ret = vec!( + Friend { name: "친구3".to_string(), age: Some(30) }, + Friend { name: "친구1".to_string(), age: Some(20) } +); +assert_eq!(json, ret); + +let json = selector("$..friends[1]").unwrap(); + +let ret = vec!( + Friend { name: "친구4".to_string(), age: None }, + Friend { name: "친구2".to_string(), age: Some(20) } +); + +assert_eq!(json, ret); +``` + +</details> + +<details><summary><b>Rust - jsonpath::delete(value: &Value, path: &str)</b></summary> + +```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"} +]})); +``` + +</details> + +<details><summary><b>Rust - jsonpath::replace_with<F: FnMut(&Value) -> Value>(value: &Value, path: &str, fun: &mut F)</b></summary> + +```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 + }; + + Some(json!(age)) +}).unwrap(); + +assert_eq!(ret, json!({ + "school": { + "friends": [ + {"name": "친구1", "age": 40}, + {"name": "친구2", "age": 40} + ] + }, + "friends": [ + {"name": "친구3", "age": 30}, + {"name": "친구4"} +]})); +``` + +</details> + +[Rust - Other Examples](https://github.com/freestrings/jsonpath/wiki/rust-examples) + +## Javascript API + +<details><summary><b>npm package</b></summary> + +##### jsonpath-wasm + +Goto [`jsonpath-wasm` npmjs.org](https://www.npmjs.com/package/jsonpath-wasm) + +```javascript +// browser +import * as jsonpath from "jsonpath-wasm"; +// NodeJs +const jsonpath = require('jsonpath-wasm'); +``` + +##### jsonpath-wasm +`wasm-bindgen` 리턴 타입 제약 때문에 빌더 패턴은 지원하지 않는다. + +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 retObj = selector.select(); + +console.log(JSON.stringify(ret) == JSON.stringify(retObj)); + +// => true +``` + +빌더 패턴 제약은 `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> + +```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 +``` + +</details> + +<details><summary><b>Javascript - jsonpath.compile(jsonpath: string)</b></summary> + +```javascript +let error = jsonpath.compile(''); +console.log(typeof error, error); //string 'path error' + +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 +``` + +</details> + +<details><summary><b>Javascript - jsonpath.selector(json: string|object)</b></summary> + +```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 +``` + +</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)
\ No newline at end of file |