From 802640a6da4e961e011f40ba705417e5907d4562 Mon Sep 17 00:00:00 2001 From: freestrings Date: Thu, 16 May 2019 14:14:09 +0900 Subject: [PATCH] jsonpath-rs add "map", "get" function --- Cargo.toml | 2 +- benches/bench_native.sh | 3 +++ benches/bench_wasm.sh | 4 +++ benches/javascript/bench.js | 17 +++++++++++++ nodejs/README.md | 22 +++++++++++++--- nodejs/lib/index.js | 28 ++++++++++++++++++--- nodejs/native/Cargo.toml | 4 +-- nodejs/native/src/lib.rs | 50 ++++++++++++++++++++++++++++++++++--- nodejs/package-lock.json | 2 +- nodejs/package.json | 2 +- nodejs/test/index.spec.js | 25 ++++++++++++++++--- 11 files changed, 142 insertions(+), 17 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3bd20ec..52ca42a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "jsonpath_lib" -version = "0.1.12" +version = "0.1.13" authors = ["Changseok Han "] description = "It is JsonPath engine written in Rust. it provide a similar API interface in Webassembly and Javascript also. - Webassembly Demo: https://freestrings.github.io/jsonpath" diff --git a/benches/bench_native.sh b/benches/bench_native.sh index e056714..efb6a83 100755 --- a/benches/bench_native.sh +++ b/benches/bench_native.sh @@ -34,6 +34,9 @@ __extra () { printf "\n" sleep 1 cd "${DIR}"/javascript && echo "NodeJs - jsonpath-rs - compile: " && time ./bench.sh nativeCompile ${ITER} + printf "\n" + sleep 1 + cd "${DIR}"/javascript && echo "NodeJs - jsonpath-rs - selectorClassMap: " && time ./bench.sh nativeSelectorClassMap ${ITER} } if [ "$1" = "extra" ]; then diff --git a/benches/bench_wasm.sh b/benches/bench_wasm.sh index 56f419a..35be013 100755 --- a/benches/bench_wasm.sh +++ b/benches/bench_wasm.sh @@ -37,8 +37,12 @@ __extra () { printf "\n" sleep 1 cd "${DIR}"/javascript && echo "NodeJs - jsonpath-wasm - compile-alloc: " && time ./bench.sh wasmCompileAlloc ${ITER} + printf "\n" sleep 1 cd "${DIR}"/javascript && echo "NodeJs - jsonpath-wasm - Selector: " && time ./bench.sh wasmSelectorClass ${ITER} + printf "\n" + sleep 1 + cd "${DIR}"/javascript && echo "NodeJs - jsonpath-wasm - Selector map: " && time ./bench.sh wasmSelectorClassMap ${ITER} } if [ "$1" = "extra" ]; then diff --git a/benches/javascript/bench.js b/benches/javascript/bench.js index 70893e2..a4c7a0b 100644 --- a/benches/javascript/bench.js +++ b/benches/javascript/bench.js @@ -71,6 +71,13 @@ function nativeSelect() { } } +function nativeSelectorClassMap() { + let selector = new jpwRs.Selector(); + for (var i = 0; i < iter; i++) { + let _ = selector.path(path).value(jsonStr).map((v) => v).get(); + } +} + function wasmSelector() { let selector = jpw.selector(getJson()); for (var i = 0; i < iter; i++) { @@ -133,6 +140,16 @@ function wasmSelectorClass() { } } +function wasmSelectorClassMap() { + let selector = new jpw.Selector(); + for (var i = 0; i < iter; i++) { + selector.path(path); + selector.value(jsonStr); + let _1 = selector.map((v) => v); + let _2 = selector.get(); + } +} + const functionName = process.argv[2]; const iter = parseInt(process.argv[3], 10); eval(functionName + "()"); \ No newline at end of file diff --git a/nodejs/README.md b/nodejs/README.md index 111460e..1859877 100644 --- a/nodejs/README.md +++ b/nodejs/README.md @@ -41,22 +41,38 @@ let jsonObj = { let selector = new jsonpath.Selector().value(jsonObj); { - let jsonObj = selector.path('$..[?(@.age >= 30)]').selectTo(); + let jsonObj = selector.path('$..[?(@.age >= 30)]').selectAs(); let resultObj = [{"name": "친구3", "age": 30}]; console.log(JSON.stringify(jsonObj) === JSON.stringify(resultObj)); } { - let jsonObj = selector.path('$..[?(@.age == 20)]').selectTo(); + let jsonObj = selector.path('$..[?(@.age == 20)]').selectAs(); let resultObj = [{"name": "친구1", "age": 20}, {"name": "친구2", "age": 20}]; console.log(JSON.stringify(jsonObj) === JSON.stringify(resultObj)); } { - let jsonObj = selector.value({"friends": [ {"name": "친구5", "age": 20} ]}).selectTo(); + let jsonObj = selector.value({"friends": [ {"name": "친구5", "age": 20} ]}).selectAs(); let resultObj = [{"name": "친구5", "age": 20}]; console.log(JSON.stringify(jsonObj) === JSON.stringify(resultObj)); } + +{ + let jsonObj1 = selector.value(jsonObj).map(function(v) { + let f1 = v[0]; + f1.age = 30; + return v; + }).get(); + + let resultObj1 = [{"name": "친구1", "age": 30}, {"name": "친구2", "age": 20}]; + console.log(JSON.stringify(jsonObj1) === JSON.stringify(resultObj1)); + + selector.path('$..[?(@.age == 20)]'); + let jsonObj2 = selector.selectAs(); + let resultObj2 = [{"name": "친구2", "age": 20}]; + console.log(JSON.stringify(jsonObj2) === JSON.stringify(resultObj2)); +} ``` ### jsonpath.select(json: string|object, jsonpath: string) diff --git a/nodejs/lib/index.js b/nodejs/lib/index.js index 315f173..20032c7 100644 --- a/nodejs/lib/index.js +++ b/nodejs/lib/index.js @@ -42,18 +42,40 @@ class Selector { if(typeof json != 'string') { json = JSON.stringify(json) } - this._selector.value_from_str(json); + this._selector.valueFromStr(json); return this; } selectToStr() { - return this._selector.select_to_str(); + return this.selectAsStr(); } selectTo() { - return JSON.parse(this.selectToStr()); + return this.selectAs(); } + selectAsStr() { + return this._selector.selectAsStr(); + } + + selectAs() { + return JSON.parse(this.selectAsStr()); + } + + map(func) { + this._selector.map((json) => { + var result = func.call(null, JSON.parse(json)); + if(typeof result !== 'string') { + result = JSON.stringify(result); + } + return result; + }); + return this; + } + + get() { + return JSON.parse(this._selector.get()); + } } module.exports = { diff --git a/nodejs/native/Cargo.toml b/nodejs/native/Cargo.toml index 28b1339..2e6238a 100644 --- a/nodejs/native/Cargo.toml +++ b/nodejs/native/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "jsonpath4nodejs" -version = "0.1.2" +version = "0.1.3" authors = ["Changseok Han "] description = "jsonpath_lib bindings for nodejs" keywords = ["library", "jsonpath", "json", "nodejs"] @@ -14,7 +14,7 @@ exclude = ["artifacts.json", "index.node"] neon-build = "0.2.0" [dependencies] -jsonpath_lib = "0.1.12" +jsonpath_lib = "0.1.13" neon = "0.2.0" neon-serde = "0.1.1" serde_json = { version = "1.0", features = ["preserve_order"] } diff --git a/nodejs/native/src/lib.rs b/nodejs/native/src/lib.rs index c24ae13..ab20da7 100644 --- a/nodejs/native/src/lib.rs +++ b/nodejs/native/src/lib.rs @@ -139,7 +139,7 @@ declare_types! { Ok(JsUndefined::new().upcast()) } - method value_from_str(mut ctx) { + method valueFromStr(mut ctx) { let mut this = ctx.this(); let json_str = ctx.argument::(0)?.value(); @@ -151,13 +151,13 @@ declare_types! { Ok(JsUndefined::new().upcast()) } - method select_to_str(mut ctx) { + method selectAsStr(mut ctx) { let mut this = ctx.this(); let result = { let guard = ctx.lock(); let mut this = this.borrow_mut(&guard); - this.selector.select_to_str() + this.selector.select_as_str() }; match result { @@ -165,6 +165,50 @@ declare_types! { Err(e) => panic!("{:?}", e) } } + + method map(mut ctx) { + let null = ctx.null(); + let mut this = ctx.this(); + + let func = ctx.argument::(0)?; + + let value = { + let guard = ctx.lock(); + let mut this = this.borrow_mut(&guard); + match this.selector.select_as_str() { + Ok(v) => v, + Err(e) => panic!("{:?}", e) + } + }; + + let js_value = JsString::new(&mut ctx, &value); + let json_str = func.call(&mut ctx, null, vec![js_value])? + .downcast::() + .or_throw(&mut ctx)? + .value(); + { + let guard = ctx.lock(); + let mut this = this.borrow_mut(&guard); + let _ = this.selector.value_from_str(&json_str); + } + + Ok(JsUndefined::new().upcast()) + } + + method get(mut ctx) { + let mut this = ctx.this(); + + let result = { + let guard = ctx.lock(); + let mut this = this.borrow_mut(&guard); + match this.selector.get() { + Ok(v) => v, + Err(e) => panic!("{:?}", e) + } + }; + + Ok(JsString::new(&mut ctx, &result.to_string()).upcast()) + } } } register_module!(mut m, { diff --git a/nodejs/package-lock.json b/nodejs/package-lock.json index eb3587c..6608016 100644 --- a/nodejs/package-lock.json +++ b/nodejs/package-lock.json @@ -1,6 +1,6 @@ { "name": "jsonpath-rs", - "version": "0.1.9", + "version": "0.1.11", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/nodejs/package.json b/nodejs/package.json index 2f3592a..a25435f 100644 --- a/nodejs/package.json +++ b/nodejs/package.json @@ -1,6 +1,6 @@ { "name": "jsonpath-rs", - "version": "0.1.10", + "version": "0.1.11", "description": "It is JsonPath implementation. The core implementation is written in Rust", "author": "Changseok Han ", "license": "MIT", diff --git a/nodejs/test/index.spec.js b/nodejs/test/index.spec.js index 777f955..99ee6e8 100644 --- a/nodejs/test/index.spec.js +++ b/nodejs/test/index.spec.js @@ -444,7 +444,7 @@ describe('README test', () => { let selector = new jsonpath.Selector().value(jsonObj); { - let jsonObj = selector.path('$..[?(@.age >= 30)]').selectTo(); + let jsonObj = selector.path('$..[?(@.age >= 30)]').selectAs(); let resultObj = [{"name": "친구3", "age": 30}]; if(JSON.stringify(jsonObj) !== JSON.stringify(resultObj)) { throw 'jsonpath.Selector: $..[?(@.age >= 30)]'; @@ -452,7 +452,7 @@ describe('README test', () => { } { - let jsonObj = selector.path('$..[?(@.age == 20)]').selectTo(); + let jsonObj = selector.path('$..[?(@.age == 20)]').selectAs(); let resultObj = [{"name": "친구1", "age": 20}, {"name": "친구2", "age": 20}]; if(JSON.stringify(jsonObj) !== JSON.stringify(resultObj)) { throw 'jsonpath.Selector: $..[?(@.age >= 20)]'; @@ -460,13 +460,32 @@ describe('README test', () => { } { - let jsonObj = selector.value({"friends": [ {"name": "친구5", "age": 20} ]}).selectTo(); + let jsonObj = selector.value({"friends": [ {"name": "친구5", "age": 20} ]}).selectAs(); let resultObj = [{"name": "친구5", "age": 20}]; if(JSON.stringify(jsonObj) !== JSON.stringify(resultObj)) { throw 'jsonpath.Selector: change value'; } } + { + let jsonObj1 = selector.value(jsonObj).map(function(v) { + let f1 = v[0]; + f1.age = 30; + return v; + }).get(); + + let resultObj1 = [{"name": "친구1", "age": 30}, {"name": "친구2", "age": 20}]; + if(JSON.stringify(jsonObj1) !== JSON.stringify(resultObj1)) { + throw 'jsonpath.Selector.map'; + } + + let jsonObj2 = selector.path('$..[?(@.age == 20)]').selectAs(); + let resultObj2 = [{"name": "친구2", "age": 20}]; + if(JSON.stringify(jsonObj2) !== JSON.stringify(resultObj2)) { + throw 'jsonpath.Selector.map and then select'; + } + } + done(); });