diff --git a/README.md b/README.md index 8aaa4fd..8855383 100644 --- a/README.md +++ b/README.md @@ -15,42 +15,17 @@ It is JsonPath [JsonPath](https://goessner.net/articles/JsonPath/) engine writte ## Rust API -- [jsonpath_lib crate](#jsonpath_lib-crate) -- [Rust - jsonpath::Selector struct](#rust---jsonpathselector-struct) -- [Rust - jsonpath::SelectorMut struct](#rust---jsonpathselectormut-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\(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\(json: &serde_json::value::Value)](#rust---jsonpathselector_ast-serdededeserializeownedjson-serde_jsonvaluevalue) -- [Rust - jsonpath::delete(value: &Value, path: &str)](#rust---jsonpathdeletevalue-value-path-str) -- [Rust - jsonpath::replace_with\ Value`\>(value: &Value, path: &str, fun: &mut F)](#rust---jsonpathreplace_withf-fnmutvalue---valuevalue-value-path-str-fun-mut-f) -- [Rust - Other Examples](https://github.com/freestrings/jsonpath/wiki/rust-examples) +
jsonpath_lib crate -## Javascript API - -- [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 - Other Examples](https://github.com/freestrings/jsonpath/wiki/Javascript-examples) - ---- - -### Rust API - -#### jsonpath_lib crate -[Go to creates.io](https://crates.io/crates/jsonpath_lib) +Go to [`jsonpath_lib` creates.io](https://crates.io/crates/jsonpath_lib) ```rust extern crate jsonpath_lib as jsonpath; -#[macro_use] -extern crate serde_json; ``` -#### Rust - jsonpath::Selector struct +
+ +
Rust - jsonpath::Selector struct ```rust #[derive(Deserialize, PartialEq, Debug)] @@ -87,7 +62,9 @@ let result = selector.select_as::().unwrap(); assert_eq!(vec![Friend { name: "친구3".to_string(), age: Some(30) }], result); ``` -#### Rust - jsonpath::SelectorMut struct +
+ +
Rust - jsonpath::SelectorMut struct ```rust let json_obj = json!({ @@ -131,7 +108,9 @@ assert_eq!(result, json!({ ]})); ``` -#### Rust - jsonpath::select(json: &serde_json::value::Value, jsonpath: &str) +
+ +
Rust - jsonpath::select(json: &serde_json::value::Value, jsonpath: &str) ```rust let json_obj = json!({ @@ -154,7 +133,10 @@ assert_eq!(json, vec![ ]); ``` -#### Rust - jsonpath::select_as_str(json: &str, jsonpath: &str) +
+ + +
Rust - jsonpath::select_as_str(json_str: &str, jsonpath: &str) ```rust let ret = jsonpath::select_as_str(r#" @@ -175,7 +157,9 @@ let ret = jsonpath::select_as_str(r#" assert_eq!(ret, r#"[{"name":"친구3","age":30},{"name":"친구1","age":20}]"#); ``` -#### Rust - jsonpath::select_as\(json: &str, jsonpath: &str) +
+ +
Rust - jsonpath::select_as<T: `serde::de::DeserializeOwned`>(json_str: &str, jsonpath: &str) ```rust #[derive(Deserialize, PartialEq, Debug)] @@ -208,7 +192,9 @@ let person = Person { assert_eq!(ret[0], person); ``` -#### Rust - jsonpath::compile(jsonpath: &str) +
+ +
Rust - jsonpath::compile(jsonpath: &str) ```rust let mut template = jsonpath::compile("$..friends[0]"); @@ -233,7 +219,9 @@ assert_eq!(json, vec![ ]); ``` -#### Rust - jsonpath::selector(json: &serde_json::value::Value) +
+ +
Rust - jsonpath::selector(json: &serde_json::value::Value) ```rust let json_obj = json!({ @@ -265,7 +253,9 @@ assert_eq!(json, vec![ ]); ``` -#### Rust - jsonpath::selector_as\(json: &serde_json::value::Value) +
+ +
Rust - jsonpath::selector_as<T: serde::de::DeserializeOwned>(json: &serde_json::value::Value) ```rust let json_obj = json!({ @@ -306,7 +296,9 @@ let ret = vec!( assert_eq!(json, ret); ``` -#### Rust - jsonpath::delete(value: &Value, path: &str) +
+ +
Rust - jsonpath::delete(value: &Value, path: &str) ```rust let json_obj = json!({ @@ -336,7 +328,9 @@ assert_eq!(ret, json!({ ]})); ``` -#### Rust - jsonpath::replace_with\ Value`\>(value: &Value, path: &str, fun: &mut F) +
+ +
Rust - jsonpath::replace_with<F: FnMut(&Value) -> Value>(value: &Value, path: &str, fun: &mut F) ```rust let json_obj = json!({ @@ -373,14 +367,19 @@ assert_eq!(ret, json!({ {"name": "친구4"} ]})); ``` ---- -### Javascript API +
-#### npm package +[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"; @@ -390,13 +389,15 @@ const jsonpath = require('jsonpath-wasm'); ##### jsonpath-rs (NodeJS only) -[Goto npmjs.org](https://www.npmjs.com/package/jsonpath-rs) +Goto [`jsonpath-rs` npmjs.org](https://www.npmjs.com/package/jsonpath-rs) ```javascript const jsonpath = require('jsonpath-rs'); ``` -#### javascript - Selector class +
+ +
Javascript - jsonpath.Selector class ##### jsonpath-wasm `wasm-bindgen` 리턴 타입 제약 때문에 빌더 패턴은 지원하지 않는다. @@ -465,7 +466,75 @@ console.log(JSON.stringify(ret) == JSON.stringify(retObj)); // => true ``` -#### Javascript - jsonpath.select(json: string|object, jsonpath: string) +
+ +
Javascript - jsonpath.SelectorMut class + +`since 0.2.0` + +빌더 패턴 제약은 `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 = { @@ -498,7 +567,9 @@ console.log( // => true, true ``` -#### Javascript - jsonpath.compile(jsonpath: string) +
+ +
Javascript - jsonpath.compile(jsonpath: string) ```javascript let template = jsonpath.compile('$..friends[0]'); @@ -557,8 +628,10 @@ console.log( // => true, true ``` -#### Javascript - jsonpath.selector(json: string|object) - +
+ +
Javascript - jsonpath.selector(json: string|object) + ```javascript let jsonObj = { "school": { @@ -596,4 +669,82 @@ console.log( ); // => true, true -``` \ No newline at end of file +``` + +
+ +
Javascript - jsonpath.deleteValue(json: string|object, path: string) + +`since 0.2.0` + +```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 + +`since 0.2.0` + +```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) \ No newline at end of file diff --git a/nodejs/lib/index.js b/nodejs/lib/index.js index 5a6eb82..bf962f7 100644 --- a/nodejs/lib/index.js +++ b/nodejs/lib/index.js @@ -89,7 +89,7 @@ class SelectorMut { } path(path) { - this.path = path; + this._path = path; return this; } @@ -97,43 +97,43 @@ class SelectorMut { if(typeof json != 'string') { json = JSON.stringify(json) } - this.json = json; + this._json = json; return this; } deleteValue() { let selector = new _SelectorMut(); - if(!this.path) { + if(!this._path) { selector.emptyPathError(); return; } - if(!this.json) { + if(!this._json) { selector.emptyValueError(); return; } - this.json = deleteValue(this.json, this.path); + this._json = deleteValue(this._json, this._path); return this; } replaceWith(fun) { let selector = new _SelectorMut(); - if(!this.path) { + if(!this._path) { selector.emptyPathError(); return; } - if(!this.json) { + if(!this._json) { selector.emptyValueError(); return; } - this.json = replaceWith(this.json, this.path, fun); + this._json = replaceWith(this._json, this._path, fun); return this; } take() { - let json = this.json; - delete this.json; + let json = this._json; + delete this._json; return json; } } diff --git a/nodejs/native/Cargo.toml b/nodejs/native/Cargo.toml index 9b0f1ce..071e68d 100644 --- a/nodejs/native/Cargo.toml +++ b/nodejs/native/Cargo.toml @@ -14,7 +14,8 @@ exclude = ["artifacts.json", "index.node"] neon-build = "0.2.0" [dependencies] -jsonpath_lib = "0.2.0" +#jsonpath_lib = "0.2.0" +jsonpath_lib = {path="../../"} neon = "0.2.0" neon-serde = "0.1.1" serde_json = { version = "1.0", features = ["preserve_order"] } diff --git a/nodejs/test/index.spec.js b/nodejs/test/index.spec.js index 7e5fa61..c948aae 100644 --- a/nodejs/test/index.spec.js +++ b/nodejs/test/index.spec.js @@ -550,6 +550,64 @@ describe('README test', () => { done(); }); + it('jsonpath.SelectorMut', (done) => { + 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).deleteValue(); + + let resultObj = { + 'school': {'friends': [null, null]}, + 'friends': [ + {'name': '친구3', 'age': 30}, + {'name': '친구4'}, + ], + }; + if (JSON.stringify(selector.take()) !== JSON.stringify(resultObj)) { + throw 'jsonpath.SelectorMut.deleteValue'; + } + } + + { + selector.value(jsonObj).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'}, + ], + }; + if (JSON.stringify(selector.take()) !== JSON.stringify(resultObj)) { + throw 'jsonpath.SelectorMut.replaceWith'; + } + } + + done(); + }); + it('jsonpath.select(json: string|object, jsonpath: string)', (done) => { let jsonObj = { "school": { @@ -679,4 +737,64 @@ describe('README test', () => { done(); }); + + it('jsonpath.deleteValue(json: string|object, path: string)', (done) => { + 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]'); + + if(JSON.stringify(result) === JSON.stringify({ + "school": { "friends": [null, null]}, + "friends": [null, null] + })) { + done(); + } + }); + + it('jsonpath.replaceWith(json: string|object, path: string, fun: function(json: object) => json: object', (done) => { + 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; + }); + + if(JSON.stringify(result) === JSON.stringify({ + "school": { + "friends": [ + {"name": "친구1", "age": 40}, + {"name": "친구2", "age": 20} + ] + }, + "friends": [ + {"name": "친구3", "age": 60}, + {"name": "친구4"} + ] + })) { + done(); + } + }); }); \ No newline at end of file diff --git a/tests/mutable.rs b/tests/mutable.rs index b61fa07..d67e424 100644 --- a/tests/mutable.rs +++ b/tests/mutable.rs @@ -37,4 +37,29 @@ fn selector_mut() { .select().unwrap(); assert_eq!(vec![&json!("a"), &json!("a"), &json!("a"), &json!("a"), &json!("a")], result); +} + +#[test] +fn selector_mut_delete_array() { + setup(); + + let json = serde_json::from_str(r#"{ + "school": { + "friends": [ + {"name": "친구1", "age": 20}, + {"name": "친구2", "age": 20} + ] + }, + "friends": [ + {"name": "친구3", "age": 30}, + {"name": "친구4"} + ] + }"#).unwrap(); + + let json1 = jsonpath::delete(json, "$..friends[0]").unwrap(); + + println!("{:?}", json1); + + let mut json2 = jsonpath::delete(json1, "$..friends[1]").unwrap(); + } \ No newline at end of file diff --git a/wasm/tests/test/index.spec.js b/wasm/tests/test/index.spec.js index c17bcbd..97d7dc7 100644 --- a/wasm/tests/test/index.spec.js +++ b/wasm/tests/test/index.spec.js @@ -478,7 +478,7 @@ describe('SelectorMut test', () => { })) { done(); } - }) + }); it('SeletorMut replaceWith', (done) => { let jsonObjNew = JSON.parse(JSON.stringify(jsonObj)); @@ -509,7 +509,7 @@ describe('SelectorMut test', () => { })) { done(); } - }) + }); }); describe('Selector test', () => { @@ -574,6 +574,65 @@ describe('README test', () => { done(); }); + it('jsonpath.SelectorMut', (done) => { + 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'}, + ], + }; + if (JSON.stringify(selector.take()) !== JSON.stringify(resultObj)) { + throw 'jsonpath.SelectorMut.deleteValue'; + } + } + + { + 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'}, + ], + }; + if (JSON.stringify(selector.take()) !== JSON.stringify(resultObj)) { + throw 'jsonpath.SelectorMut.replaceWith'; + } + } + + done(); + }); + it('jsonpath.select(json: string|object, jsonpath: string)', (done) => { let jsonObj = { 'school': { @@ -702,4 +761,64 @@ describe('README test', () => { done(); }); + + it('jsonpath.deleteValue(json: string|object, path: string)', (done) => { + 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]'); + + if (JSON.stringify(result) === JSON.stringify({ + 'school': {'friends': [null, null]}, + 'friends': [null, null], + })) { + done(); + } + }); + + it('jsonpath.replaceWith(json: string|object, path: string, fun: function(json: object) => json: object', (done) => { + 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; + }); + + if (JSON.stringify(result) === JSON.stringify({ + 'school': { + 'friends': [ + {'name': '친구1', 'age': 40}, + {'name': '친구2', 'age': 20}, + ], + }, + 'friends': [ + {'name': '친구3', 'age': 60}, + {'name': '친구4'}, + ], + })) { + done(); + } + }); }); \ No newline at end of file