# 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
jsonpath_lib crate Go to [`jsonpath_lib` creates.io](https://crates.io/crates/jsonpath_lib) ```rust extern crate jsonpath_lib as jsonpath; ```
Rust - jsonpath::Selector struct ```rust #[derive(Deserialize, PartialEq, Debug)] struct Friend { name: String, age: Option, } 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::().unwrap(); assert_eq!(vec![Friend { name: "친구3".to_string(), age: Some(30) }], result); ```
Rust - jsonpath::SelectorMut struct ```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"} ]})); ```
Rust - jsonpath::select(json: &serde_json::value::Value, jsonpath: &str) ```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}) ]); ```
Rust - jsonpath::select_as_str(json_str: &str, jsonpath: &str) ```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}]"#); ```
Rust - jsonpath::select_as<T: `serde::de::DeserializeOwned`>(json_str: &str, jsonpath: &str) ```rust #[derive(Deserialize, PartialEq, Debug)] struct Person { name: String, age: u8, phones: Vec, } let ret: Vec = 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); ```
Rust - jsonpath::Compiled::compile(jsonpath: &str) ```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}) ]); ```
Rust - jsonpath::selector(json: &serde_json::value::Value) ```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}) ]); ```
Rust - jsonpath::selector_as<T: serde::de::DeserializeOwned>(json: &serde_json::value::Value) ```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, } let mut selector = jsonpath::selector_as::(&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); ```
Rust - jsonpath::delete(value: &Value, path: &str) ```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"} ]})); ```
Rust - jsonpath::replace_with<F: FnMut(&Value) -> Value>(value: &Value, path: &str, fun: &mut F) ```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"} ]})); ```
[Rust - Other Examples](https://github.com/freestrings/jsonpath/wiki/rust-examples) ## Javascript API
npm package ##### 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 } ```
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 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 ```
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 - jsonpath.deleteValue(json: string|object, path: string) ```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 ```
Javascript - jsonpath.replaceWith(json: string|object, path: string, fun: function(json: object) => json: object ```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 ```
[Javascript - Other Examples](https://github.com/freestrings/jsonpath/wiki/Javascript-examples)