SelectorMut WASM 적용

This commit is contained in:
freestrings 2019-06-10 18:16:08 +09:00
parent 24d18efb6f
commit ec5d76d2d6
7 changed files with 697 additions and 313 deletions

104
build-wasm.sh Executable file
View File

@ -0,0 +1,104 @@
#!/bin/bash
set -e
# project_root
DIR="$(pwd)"
WASM="${DIR}"/wasm
WASM_WWW="${WASM}"/www
WASM_WWW_BENCH="${WASM}"/www_bench
WASM_BROWSER_PKG="${WASM}"/browser_pkg
WASM_NODEJS_PKG="${WASM}"/nodejs_pkg
WASM_ALL_PKG="${WASM}"/all_pkg
WASM_TEST="${WASM}"/tests
DOCS="${DIR}"/docs
DOCS_BENCH="${DOCS}"/bench
__msg () {
echo ">>>>>>>>>>$1<<<<<<<<<<"
}
__cargo_clean () {
cd "${WASM}" && cargo clean && \
cd "${DIR}" && cargo clean
}
echo
__msg "clean wasm"
rm -rf \
"${WASM_NODEJS_PKG}" \
"${WASM_BROWSER_PKG}" \
"${WASM_ALL_PKG}" \
"${WASM_WWW}"/node_modules \
"${WASM_WWW_BENCH}"/node_modules \
"${WASM_WWW}"/dist \
"${WASM_WWW_BENCH}"/dist \
"${WASM_TEST}"/node_modules
if [ "$1" = "all" ]; then
__msg "clean all wasm"
__cargo_clean
fi
__msg "npm install: wasm"
cd "${WASM_WWW}" && npm install
__msg "npm install: wasm_bench"
cd "${WASM_WWW_BENCH}" && npm install
__msg "npm install: wasm test"
cd "${WASM_TEST}" && npm install
echo
echo
__msg "wasm-pack"
cd "${WASM}" && \
wasm-pack build --release --target=nodejs --out-dir "${WASM_NODEJS_PKG}"
cd "${WASM}" && \
wasm-pack build --release --target=browser --out-dir "${WASM_BROWSER_PKG}"
# && \
# wasm-pack test --chrome --firefox --headless
__msg "wasm npm packaging"
cp -r "${WASM_BROWSER_PKG}" "${WASM_ALL_PKG}/" && \
sed "s/require[\(]'\.\/jsonpath_wasm_bg/require\('\.\/jsonpath_wasm_nodejs/" "${WASM_NODEJS_PKG}/jsonpath_wasm.js" \
> "${WASM_ALL_PKG}/jsonpath_wasm_main.js" && \
sed "s/require[\(]'\.\/jsonpath_wasm/require\('\.\/jsonpath_wasm_main/" "${WASM_NODEJS_PKG}/jsonpath_wasm_bg.js" \
> "${WASM_ALL_PKG}/jsonpath_wasm_nodejs.js" && \
jq ".files += [\"jsonpath_wasm_nodejs.js\"]" ${WASM_ALL_PKG}/package.json \
| jq ".main = \"jsonpath_wasm_main.js\"" \
| jq ".keywords += [\"jsonpath\", \"json\", \"webassembly\", \"parsing\", \"rust\"]" \
> ${WASM_ALL_PKG}/temp.json && \
mv -v "${WASM_ALL_PKG}/temp.json" "${WASM_ALL_PKG}/package.json" && \
cd "${WASM_ALL_PKG}" && npm link
echo
__msg "link"
cd "${WASM_WWW}" && \
npm link jsonpath-wasm
cd "${WASM_WWW_BENCH}" && \
npm link jsonpath-wasm
cd "${WASM_TEST}" && \
npm link jsonpath-wasm
echo
echo
__msg "wasm test"
cd "${WASM_TEST}" && npm test
if [ "$1" = "all" ] || [ "$1" = "docs" ]; then
echo
__msg "docs"
cd "${WASM_WWW}" && \
npm run build &&
rm -f "${DOCS}"/*.js "${DOCS}"/*.wasm "${DOCS}"/*.html && \
cp "${WASM_WWW}"/dist/*.* "${DOCS}"/
cd "${WASM_WWW_BENCH}" && \
npm run build &&
rm -f "${DOCS_BENCH}"/*.js "${DOCS_BENCH}"/*.wasm "${DOCS_BENCH}"/*.html && \
cp "${WASM_WWW_BENCH}"/dist/*.* "${DOCS_BENCH}"/
fi
__msg "wasm done"

View File

@ -1,10 +1,10 @@
use std::collections::HashSet;
use array_tool::vec::{Intersect, Union};
use indexmap::IndexSet;
use serde_json::{Number, Value};
use parser::parser::*;
use indexmap::IndexSet;
fn to_f64(n: &Number) -> f64 {
if n.is_i64() {
@ -1088,10 +1088,14 @@ impl SelectorMut {
let target_opt = match *target_once {
Value::Object(ref mut map) => {
if is_last {
if let Some(v) = map.remove(token) {
map.insert(token.clone(), fun(&v));
let v = if let Some(v) = map.get(token) {
fun(v)
} else {
return;
};
map.insert(token.clone(), v);
return;
}
}
map.get_mut(token)
}

View File

@ -8,6 +8,7 @@ use serde_json::Value;
use self::jsonpath::Selector;
#[allow(dead_code)]
pub fn setup() {
let _ = env_logger::try_init();
}

View File

@ -8,6 +8,8 @@ use serde_json::Value;
use jsonpath::{Selector, SelectorMut};
mod common;
#[test]
fn readme() {
let json_obj = json!({
@ -407,6 +409,26 @@ fn readme_delete() {
]}));
}
#[test]
fn readme_delete2() {
let json_obj = common::read_json("./benches/example.json");
let ret = jsonpath::delete(json_obj, "$.store.book").unwrap();
println!("{:?}", ret);
assert_eq!(ret, json!({
"store": {
"book": null,
"bicycle": {
"color": "red",
"price": 19.95
}
},
"expensive": 10
}));
}
#[test]
fn readme_replace_with() {
let json_obj = json!({

View File

@ -1,17 +1,14 @@
extern crate cfg_if;
extern crate core;
extern crate js_sys;
extern crate jsonpath_lib as jsonpath;
extern crate serde;
extern crate serde_json;
extern crate wasm_bindgen;
extern crate web_sys;
use cfg_if::cfg_if;
use jsonpath::{JsonPathError, Parser};
use jsonpath::Selector as _Selector;
use jsonpath::SelectorMut as _SelectorMut;
use serde_json::Value;
use wasm_bindgen::*;
use wasm_bindgen::prelude::*;
cfg_if! {
@ -32,6 +29,16 @@ cfg_if! {
}
}
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console)]
fn error(s: &str);
}
macro_rules! console_error {
($($t:tt)*) => (error(&format_args!($($t)*).to_string()))
}
fn into_serde_json<D>(js_value: &JsValue) -> Result<D, String>
where D: for<'a> serde::de::Deserialize<'a>
{
@ -48,6 +55,32 @@ fn into_serde_json<D>(js_value: &JsValue) -> Result<D, String>
}
}
fn replace_fun(v: &Value, fun: &js_sys::Function) -> Value {
match JsValue::from_serde(v) {
Ok(js_v) => {
match fun.call1(&JsValue::NULL, &js_v) {
Ok(result) => {
match into_serde_json(&result) {
Ok(json) => json,
Err(e) => {
console_error!("replace_with - closure returned a invalid JSON: {:?}", e);
Value::Null
}
}
}
Err(e) => {
console_error!("replace_with - fail to call closure: {:?}", e);
Value::Null
}
}
}
Err(e) => {
console_error!("replace_with - invalid JSON object: {:?}", e);
Value::Null
}
}
}
#[wasm_bindgen]
pub fn compile(path: &str) -> JsValue {
let node = Parser::compile(path);
@ -107,15 +140,46 @@ pub fn selector(js_value: JsValue) -> JsValue {
#[wasm_bindgen]
pub fn select(js_value: JsValue, path: &str) -> JsValue {
let mut selector = _Selector::new();
let _ = selector.str_path(path);
let json = match into_serde_json(&js_value) {
Ok(json) => json,
Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e)))
};
match selector.value(&json).select() {
match jsonpath::select(&json, path) {
Ok(ret) => match JsValue::from_serde(&ret) {
Ok(ret) => ret,
Err(e) => JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e.to_string())))
},
Err(e) => JsValue::from_str(&format!("{:?}", e))
}
}
#[wasm_bindgen(catch, js_name = "deleteValue")]
pub fn delete(js_value: JsValue, path: &str) -> JsValue {
let json = match into_serde_json(&js_value) {
Ok(json) => json,
Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e)))
};
match jsonpath::delete(json, path) {
Ok(ret) => {
match JsValue::from_serde(&ret) {
Ok(ret) => ret,
Err(e) => JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e.to_string())))
}
}
Err(e) => JsValue::from_str(&format!("{:?}", e))
}
}
#[wasm_bindgen(catch, js_name = "replaceWith")]
pub fn replace_with(js_value: JsValue, path: &str, fun: js_sys::Function) -> JsValue {
let json = match into_serde_json(&js_value) {
Ok(json) => json,
Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e)))
};
match jsonpath::replace_with(json, path, &mut |v| replace_fun(v, &fun)) {
Ok(ret) => match JsValue::from_serde(&ret) {
Ok(ret) => ret,
Err(e) => JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e.to_string())))
@ -180,3 +244,95 @@ impl Selector {
}
}
}
///
/// `wasm_bindgen` 제약으로 builder-pattern을 구사 할 수 없다.
///
#[wasm_bindgen]
pub struct SelectorMut {
path: Option<String>,
value: Option<Value>,
}
#[wasm_bindgen]
impl SelectorMut {
#[wasm_bindgen(constructor)]
pub fn new() -> Self {
SelectorMut { path: None, value: None }
}
#[wasm_bindgen(catch)]
pub fn path(&mut self, path: &str) -> Result<(), JsValue> {
self.path = Some(path.to_string());
Ok(())
}
#[wasm_bindgen(catch)]
pub fn value(&mut self, value: JsValue) -> Result<(), JsValue> {
let json = into_serde_json(&value)
.map_err(|e| JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e))))?;
self.value = Some(json);
Ok(())
}
#[wasm_bindgen(catch, js_name = "deleteValue")]
pub fn delete(&mut self) -> Result<(), JsValue> {
let mut selector = _SelectorMut::new();
if let Some(path) = &self.path {
let _ = selector.str_path(path);
} else {
return Err(JsValue::from_str(&format!("{:?}", JsonPathError::EmptyPath)));
};
if let Some(value) = self.value.take() {
selector.value(value);
} else {
return Err(JsValue::from_str(&format!("{:?}", JsonPathError::EmptyValue)));
};
match selector.delete() {
Err(e) => Err(JsValue::from_str(&format!("{:?}", e))),
_ => {
self.value = selector.take();
Ok(())
}
}
}
#[wasm_bindgen(catch, js_name = replaceWith)]
pub fn replace_with(&mut self, fun: js_sys::Function) -> Result<(), JsValue> {
let mut selector = _SelectorMut::new();
if let Some(path) = &self.path {
let _ = selector.str_path(path);
} else {
return Err(JsValue::from_str(&format!("{:?}", JsonPathError::EmptyPath)));
};
if let Some(value) = self.value.take() {
selector.value(value);
} else {
return Err(JsValue::from_str(&format!("{:?}", JsonPathError::EmptyValue)));
};
match selector.replace_with(&mut |v| replace_fun(v, &fun)) {
Err(e) => Err(JsValue::from_str(&format!("{:?}", e))),
_ => {
self.value = selector.take();
Ok(())
}
}
}
#[wasm_bindgen(catch)]
pub fn take(&mut self) -> Result<JsValue, JsValue> {
match self.value.take() {
Some(ret) => match JsValue::from_serde(&ret) {
Ok(ret) => Ok(ret),
Err(e) => Err(JsValue::from_str(&format!("{:?}", e)))
},
None => Err(JsValue::from_str(&format!("{:?}", JsonPathError::EmptyValue)))
}
}
}

View File

@ -1,91 +1,91 @@
const jsonpath = require('jsonpath-wasm');
let jsonObj = {
"store": {
"book": [
'store': {
'book': [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
'category': 'reference',
'author': 'Nigel Rees',
'title': 'Sayings of the Century',
'price': 8.95,
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
'category': 'fiction',
'author': 'Evelyn Waugh',
'title': 'Sword of Honour',
'price': 12.99,
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
'category': 'fiction',
'author': 'Herman Melville',
'title': 'Moby Dick',
'isbn': '0-553-21311-3',
'price': 8.99,
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
'category': 'fiction',
'author': 'J. R. R. Tolkien',
'title': 'The Lord of the Rings',
'isbn': '0-395-19395-8',
'price': 22.99,
},
],
"bicycle": {
"color": "red",
"price": 19.95
}
'bicycle': {
'color': 'red',
'price': 19.95,
},
"expensive": 10
},
'expensive': 10,
};
let list = {
'$.store.book[*].author': [
"Nigel Rees",
"Evelyn Waugh",
"Herman Melville",
"J. R. R. Tolkien"
'Nigel Rees',
'Evelyn Waugh',
'Herman Melville',
'J. R. R. Tolkien',
],
'$..author': [
"Nigel Rees",
"Evelyn Waugh",
"Herman Melville",
"J. R. R. Tolkien"
'Nigel Rees',
'Evelyn Waugh',
'Herman Melville',
'J. R. R. Tolkien',
],
'$.store.*': [
[
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
'category': 'reference',
'author': 'Nigel Rees',
'title': 'Sayings of the Century',
'price': 8.95,
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
'category': 'fiction',
'author': 'Evelyn Waugh',
'title': 'Sword of Honour',
'price': 12.99,
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
'category': 'fiction',
'author': 'Herman Melville',
'title': 'Moby Dick',
'isbn': '0-553-21311-3',
'price': 8.99,
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
'category': 'fiction',
'author': 'J. R. R. Tolkien',
'title': 'The Lord of the Rings',
'isbn': '0-395-19395-8',
'price': 22.99,
},
],
{
"color": "red",
"price": 19.95
}
'color': 'red',
'price': 19.95,
},
],
'$.store..price': [
@ -93,266 +93,266 @@ let list = {
12.99,
8.99,
22.99,
19.95
19.95,
],
'$..book[2]': [
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
}
'category': 'fiction',
'author': 'Herman Melville',
'title': 'Moby Dick',
'isbn': '0-553-21311-3',
'price': 8.99,
},
],
'$..book[-2]': [
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
}
'category': 'fiction',
'author': 'Herman Melville',
'title': 'Moby Dick',
'isbn': '0-553-21311-3',
'price': 8.99,
},
],
'$..book[0,1]': [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
'category': 'reference',
'author': 'Nigel Rees',
'title': 'Sayings of the Century',
'price': 8.95,
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
}
'category': 'fiction',
'author': 'Evelyn Waugh',
'title': 'Sword of Honour',
'price': 12.99,
},
],
'$..book[:2]': [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
'category': 'reference',
'author': 'Nigel Rees',
'title': 'Sayings of the Century',
'price': 8.95,
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
}
'category': 'fiction',
'author': 'Evelyn Waugh',
'title': 'Sword of Honour',
'price': 12.99,
},
],
'$..book[1:2]': [
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
}
'category': 'fiction',
'author': 'Evelyn Waugh',
'title': 'Sword of Honour',
'price': 12.99,
},
],
'$..book[-2:]': [
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
'category': 'fiction',
'author': 'Herman Melville',
'title': 'Moby Dick',
'isbn': '0-553-21311-3',
'price': 8.99,
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
'category': 'fiction',
'author': 'J. R. R. Tolkien',
'title': 'The Lord of the Rings',
'isbn': '0-395-19395-8',
'price': 22.99,
},
],
'$..book[2:]': [
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
'category': 'fiction',
'author': 'Herman Melville',
'title': 'Moby Dick',
'isbn': '0-553-21311-3',
'price': 8.99,
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
'category': 'fiction',
'author': 'J. R. R. Tolkien',
'title': 'The Lord of the Rings',
'isbn': '0-395-19395-8',
'price': 22.99,
},
],
'$..book[?(@.isbn)]': [
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
'category': 'fiction',
'author': 'Herman Melville',
'title': 'Moby Dick',
'isbn': '0-553-21311-3',
'price': 8.99,
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
'category': 'fiction',
'author': 'J. R. R. Tolkien',
'title': 'The Lord of the Rings',
'isbn': '0-395-19395-8',
'price': 22.99,
},
],
'$.store.book[?(@.price < 10)]': [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
'category': 'reference',
'author': 'Nigel Rees',
'title': 'Sayings of the Century',
'price': 8.95,
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
}
'category': 'fiction',
'author': 'Herman Melville',
'title': 'Moby Dick',
'isbn': '0-553-21311-3',
'price': 8.99,
},
],
'$..*': [
{
"book": [
'book': [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
'category': 'reference',
'author': 'Nigel Rees',
'title': 'Sayings of the Century',
'price': 8.95,
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
'category': 'fiction',
'author': 'Evelyn Waugh',
'title': 'Sword of Honour',
'price': 12.99,
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
'category': 'fiction',
'author': 'Herman Melville',
'title': 'Moby Dick',
'isbn': '0-553-21311-3',
'price': 8.99,
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
'category': 'fiction',
'author': 'J. R. R. Tolkien',
'title': 'The Lord of the Rings',
'isbn': '0-395-19395-8',
'price': 22.99,
},
],
"bicycle": {
"color": "red",
"price": 19.95
}
'bicycle': {
'color': 'red',
'price': 19.95,
},
},
10,
[
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
'category': 'reference',
'author': 'Nigel Rees',
'title': 'Sayings of the Century',
'price': 8.95,
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
'category': 'fiction',
'author': 'Evelyn Waugh',
'title': 'Sword of Honour',
'price': 12.99,
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
'category': 'fiction',
'author': 'Herman Melville',
'title': 'Moby Dick',
'isbn': '0-553-21311-3',
'price': 8.99,
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
'category': 'fiction',
'author': 'J. R. R. Tolkien',
'title': 'The Lord of the Rings',
'isbn': '0-395-19395-8',
'price': 22.99,
},
],
{
"color": "red",
"price": 19.95
'color': 'red',
'price': 19.95,
},
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
'category': 'reference',
'author': 'Nigel Rees',
'title': 'Sayings of the Century',
'price': 8.95,
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
'category': 'fiction',
'author': 'Evelyn Waugh',
'title': 'Sword of Honour',
'price': 12.99,
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
'category': 'fiction',
'author': 'Herman Melville',
'title': 'Moby Dick',
'isbn': '0-553-21311-3',
'price': 8.99,
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
'category': 'fiction',
'author': 'J. R. R. Tolkien',
'title': 'The Lord of the Rings',
'isbn': '0-395-19395-8',
'price': 22.99,
},
"reference",
"Nigel Rees",
"Sayings of the Century",
'reference',
'Nigel Rees',
'Sayings of the Century',
8.95,
"fiction",
"Evelyn Waugh",
"Sword of Honour",
'fiction',
'Evelyn Waugh',
'Sword of Honour',
12.99,
"fiction",
"Herman Melville",
"Moby Dick",
"0-553-21311-3",
'fiction',
'Herman Melville',
'Moby Dick',
'0-553-21311-3',
8.99,
"fiction",
"J. R. R. Tolkien",
"The Lord of the Rings",
"0-395-19395-8",
'fiction',
'J. R. R. Tolkien',
'The Lord of the Rings',
'0-395-19395-8',
22.99,
"red",
19.95
'red',
19.95,
],
'$..book[ ?( (@.price < 13 || $.store.bicycle.price < @.price) && @.price <=10 ) ]': [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
'category': 'reference',
'author': 'Nigel Rees',
'title': 'Sayings of the Century',
'price': 8.95,
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
}
]
'category': 'fiction',
'author': 'Herman Melville',
'title': 'Moby Dick',
'isbn': '0-553-21311-3',
'price': 8.99,
},
],
};
describe('compile test', () => {
@ -396,24 +396,122 @@ describe('filter test', () => {
for (var i in list) {
it(i, (done) => {
run(done, i, list[i]);
})
});
}
it('object equal', (done) => {
let selector = new jsonpath.Selector();
selector.path('$..[?(@.a == 1)]');
selector.value({
"a": 1,
"b" : {"a": 1},
"c" : {"a": 1}
'a': 1,
'b': {'a': 1},
'c': {'a': 1},
});
let result = selector.select();
if (JSON.stringify(result) === JSON.stringify([ {"a": 1}, {"a": 1} ])) {
if (JSON.stringify(result) === JSON.stringify([{'a': 1}, {'a': 1}])) {
done();
}
});
});
describe('SelectorMut test', () => {
it('delete', (done) => {
let jsonObjNew = JSON.parse(JSON.stringify(jsonObj));
let result = jsonpath.deleteValue(jsonObjNew, '$.store.book');
if (JSON.stringify(result) === JSON.stringify({
'store': {
'book': null,
'bicycle': {
'color': 'red',
'price': 19.95,
},
},
'expensive': 10,
})) {
done();
}
});
it('replaceWith', (done) => {
let jsonObjNew = JSON.parse(JSON.stringify(jsonObj));
let result = jsonpath.replaceWith(jsonObjNew, '$.store.book', (v) => {
let ret = v[0];
ret.price = 9;
return ret;
});
if (JSON.stringify(result) === JSON.stringify({
'store': {
'book': {
'category': 'reference',
'author': 'Nigel Rees',
'title': 'Sayings of the Century',
'price': 9,
},
'bicycle': {
'color': 'red',
'price': 19.95,
},
},
'expensive': 10,
})) {
done();
}
});
it('SeletorMut delete', (done) => {
let jsonObjNew = JSON.parse(JSON.stringify(jsonObj));
let selector = new jsonpath.SelectorMut();
selector.path('$.store.book');
selector.value(jsonObjNew);
selector.deleteValue();
let result = selector.take();
if (JSON.stringify(result) === JSON.stringify({
'store': {
'book': null,
'bicycle': {
'color': 'red',
'price': 19.95,
},
},
'expensive': 10,
})) {
done();
}
})
it('SeletorMut replaceWith', (done) => {
let jsonObjNew = JSON.parse(JSON.stringify(jsonObj));
let selector = new jsonpath.SelectorMut();
selector.path('$.store.book');
selector.value(jsonObjNew);
selector.replaceWith((v) => {
let ret = v[0];
ret.price = 9;
return ret;
});
let result = selector.take();
if (JSON.stringify(result) === JSON.stringify({
'store': {
'book': {
'category': 'reference',
'author': 'Nigel Rees',
'title': 'Sayings of the Century',
'price': 9,
},
'bicycle': {
'color': 'red',
'price': 19.95,
},
},
'expensive': 10,
})) {
done();
}
})
});
describe('Selector test', () => {
it('select', (done) => {
let selector = new jsonpath.Selector();
@ -431,16 +529,16 @@ describe('Selector test', () => {
describe('README test', () => {
it('jsonpath.Selector', (done) => {
let jsonObj = {
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
'school': {
'friends': [
{'name': '친구1', 'age': 20},
{'name': '친구2', 'age': 20},
],
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]
'friends': [
{'name': '친구3', 'age': 30},
{'name': '친구4'},
],
};
let selector = new jsonpath.Selector();
@ -449,7 +547,7 @@ describe('README test', () => {
{
selector.path('$..[?(@.age >= 30)]');
let jsonObj = selector.select();
let resultObj = [{"name": "친구3", "age": 30}];
let resultObj = [{'name': '친구3', 'age': 30}];
if (JSON.stringify(jsonObj) !== JSON.stringify(resultObj)) {
throw 'jsonpath.Selector: $..[?(@.age >= 30)]';
}
@ -458,16 +556,16 @@ describe('README test', () => {
{
selector.path('$..[?(@.age == 20)]');
let jsonObj = selector.select();
let resultObj = [{"name": "친구1", "age": 20}, {"name": "친구2", "age": 20}];
let resultObj = [{'name': '친구1', 'age': 20}, {'name': '친구2', 'age': 20}];
if (JSON.stringify(jsonObj) !== JSON.stringify(resultObj)) {
throw 'jsonpath.Selector: $..[?(@.age >= 20)]';
}
}
{
selector.value({"friends": [ {"name": "친구5", "age": 20} ]});
selector.value({'friends': [{'name': '친구5', 'age': 20}]});
let jsonObj = selector.select();
let resultObj = [{"name": "친구5", "age": 20}];
let resultObj = [{'name': '친구5', 'age': 20}];
if (JSON.stringify(jsonObj) !== JSON.stringify(resultObj)) {
throw 'jsonpath.Selector: change value';
}
@ -478,24 +576,23 @@ describe('README test', () => {
it('jsonpath.select(json: string|object, jsonpath: string)', (done) => {
let jsonObj = {
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
'school': {
'friends': [
{'name': '친구1', 'age': 20},
{'name': '친구2', 'age': 20},
],
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]
'friends': [
{'name': '친구3', 'age': 30},
{'name': '친구4'},
],
};
let ret = [
{"name": "친구3", "age": 30},
{"name": "친구1", "age": 20}
{'name': '친구3', 'age': 30},
{'name': '친구1', 'age': 20},
];
let selectAsString = jsonpath.select(JSON.stringify(jsonObj), '$..friends[0]');
let selectAsObj = jsonpath.select(jsonObj, '$..friends[0]');
@ -513,21 +610,21 @@ describe('README test', () => {
let template = jsonpath.compile('$..friends[0]');
let jsonObj = {
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
'school': {
'friends': [
{'name': '친구1', 'age': 20},
{'name': '친구2', 'age': 20},
],
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]
'friends': [
{'name': '친구3', 'age': 30},
{'name': '친구4'},
],
};
let ret = [
{"name": "친구3", "age": 30},
{"name": "친구1", "age": 20}
{'name': '친구3', 'age': 30},
{'name': '친구1', 'age': 20},
];
let selectAsString = template(JSON.stringify(jsonObj));
@ -541,18 +638,18 @@ describe('README test', () => {
}
let jsonObj2 = {
"school": {
"friends": [
{"name": "Millicent Norman"},
{"name": "Vincent Cannon"}
]
'school': {
'friends': [
{'name': 'Millicent Norman'},
{'name': 'Vincent Cannon'},
],
},
"friends": [ {"age": 30}, {"age": 40} ]
'friends': [{'age': 30}, {'age': 40}],
};
let ret2 = [
{"age": 30},
{"name": "Millicent Norman"}
{'age': 30},
{'name': 'Millicent Norman'},
];
let selectAsString2 = template(JSON.stringify(jsonObj2));
@ -570,26 +667,26 @@ describe('README test', () => {
it('jsonpath.selector(json: string|object)', (done) => {
let jsonObj = {
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
'school': {
'friends': [
{'name': '친구1', 'age': 20},
{'name': '친구2', 'age': 20},
],
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]
'friends': [
{'name': '친구3', 'age': 30},
{'name': '친구4'},
],
};
let ret1 = [
{"name": "친구3", "age": 30},
{"name": "친구1", "age": 20}
{'name': '친구3', 'age': 30},
{'name': '친구1', 'age': 20},
];
let ret2 = [
{"name": "친구4"},
{"name": "친구2", "age": 20}
{'name': '친구4'},
{'name': '친구2', 'age': 20},
];
let selector = jsonpath.selector(jsonObj);