mirror of
https://github.com/fluencelabs/jsonpath
synced 2025-03-16 15:30:50 +00:00
Javascript Selector 유닛테스트 완료
This commit is contained in:
parent
d263e30c91
commit
1c3656460e
604
README.md
604
README.md
@ -16,21 +16,9 @@ It is an implementation for [JsonPath](https://goessner.net/articles/JsonPath/)
|
||||
|
||||
To enjoy Rust!
|
||||
|
||||
## API
|
||||
## Rust API
|
||||
|
||||
[With Javascript](#with-javascript)
|
||||
|
||||
- [jsonpath-wasm library](#jsonpath-wasm-library)
|
||||
- [jsonpath-rs library](#jsonpath-rs-library-only-nodejs)
|
||||
- [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 - alloc_json, dealloc_json](#javascript---alloc_json-dealloc_json)
|
||||
- [Javascript-wasm - examples](https://github.com/freestrings/jsonpath/wiki/Javascript-examples)
|
||||
|
||||
[With Rust](#with-rust)
|
||||
|
||||
- [jsonpath_lib library](#jsonpath_lib-library)
|
||||
- [jsonpath_lib crate](#jsonpath_lib-crate)
|
||||
- [Rust - jsonpath::Selector struct](#rust---jsonpathselector-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)
|
||||
@ -40,15 +28,262 @@ To enjoy Rust!
|
||||
- [Rust - jsonpath::selector_as\<T: `serde::de::DeserializeOwned`\>(json: &serde_json::value::Value)](#rust---jsonpathselector_ast-serdededeserializeownedjson-serde_jsonvaluevalue)
|
||||
- [Rust - examples](https://github.com/freestrings/jsonpath/wiki/rust-examples)
|
||||
|
||||
[Simple time check - webassembly](https://github.com/freestrings/jsonpath/wiki/Simple-timecheck---jsonpath-wasm)
|
||||
## Javascript API
|
||||
|
||||
[Simple time check - native addon for NodeJs](https://github.com/freestrings/jsonpath/wiki/Simple-timecheck-jsonpath-native)
|
||||
- [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 - allocJson, deallocJson (Webassembly Only)](#javascript---allocjson-deallocjson-webassembly-only)
|
||||
- [Javascript - examples](https://github.com/freestrings/jsonpath/wiki/Javascript-examples)
|
||||
|
||||
## With Javascript
|
||||
## Simple time check
|
||||
- [jsonpath-wasm](https://github.com/freestrings/jsonpath/wiki/Simple-timecheck---jsonpath-wasm)
|
||||
- [jsonpath-rs](https://github.com/freestrings/jsonpath/wiki/Simple-timecheck-jsonpath-native)
|
||||
|
||||
### jsonpath-wasm library
|
||||
---
|
||||
|
||||
### Rust API
|
||||
|
||||
#### jsonpath_lib crate
|
||||
[Go to 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
|
||||
#[derive(Serialize, 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_from_str(&serde_json::to_string(&json_obj).unwrap() /*&str*/).unwrap()
|
||||
// .value_from(&json_obj /*&impl serde::ser::Serialize*/).unwrap()
|
||||
.value((&json_obj /*serde_json::value::Value*/ ).into()).unwrap()
|
||||
.select_to_value().unwrap();
|
||||
|
||||
assert_eq!(json!([{"name": "친구3", "age": 30}]), result);
|
||||
|
||||
let result = selector.select_to_str().unwrap();
|
||||
assert_eq!(r#"[{"name":"친구3","age":30}]"#, result);
|
||||
|
||||
let result = selector.select_to::<Vec<Friend>>().unwrap();
|
||||
assert_eq!(vec![Friend { name: "친구3".to_string(), age: Some(30) }], result);
|
||||
```
|
||||
|
||||
#### 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();
|
||||
|
||||
let ret = json!([
|
||||
{"name": "친구3", "age": 30},
|
||||
{"name": "친구1", "age": 20}
|
||||
]);
|
||||
assert_eq!(json, ret);
|
||||
```
|
||||
|
||||
#### Rust - jsonpath::select_as_str(json: &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, jsonpath: &str)
|
||||
|
||||
```rust
|
||||
#[derive(Deserialize, PartialEq, Debug)]
|
||||
struct Person {
|
||||
name: String,
|
||||
age: u8,
|
||||
phones: Vec<String>,
|
||||
}
|
||||
|
||||
let ret: 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!(person, ret);
|
||||
```
|
||||
|
||||
#### Rust - jsonpath::compile(jsonpath: &str)
|
||||
|
||||
```rust
|
||||
let mut template = jsonpath::compile("$..friends[0]");
|
||||
|
||||
let json_obj = json!({
|
||||
"school": {
|
||||
"friends": [
|
||||
{"name": "친구1", "age": 20},
|
||||
{"name": "친구2", "age": 20}
|
||||
]
|
||||
},
|
||||
"friends": [
|
||||
{"name": "친구3", "age": 30},
|
||||
{"name": "친구4"}
|
||||
]});
|
||||
|
||||
let json = template(&json_obj).unwrap();
|
||||
|
||||
let ret = json!([
|
||||
{"name": "친구3", "age": 30},
|
||||
{"name": "친구1", "age": 20}
|
||||
]);
|
||||
|
||||
assert_eq!(json, ret);
|
||||
```
|
||||
|
||||
#### 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();
|
||||
|
||||
let ret = json!([
|
||||
{"name": "친구3", "age": 30},
|
||||
{"name": "친구1", "age": 20}
|
||||
]);
|
||||
|
||||
assert_eq!(json, ret);
|
||||
|
||||
let json = selector("$..friends[1]").unwrap();
|
||||
|
||||
let ret = json!([
|
||||
{"name": "친구4"},
|
||||
{"name": "친구2", "age": 20}
|
||||
]);
|
||||
|
||||
assert_eq!(json, ret);
|
||||
```
|
||||
|
||||
#### 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(Serialize, Deserialize, PartialEq, Debug)]
|
||||
struct Friend {
|
||||
name: String,
|
||||
age: Option<u8>,
|
||||
}
|
||||
|
||||
let mut selector = jsonpath::selector_as::<Vec<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);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Javascript API
|
||||
|
||||
#### npm package
|
||||
|
||||
##### jsonpath-wasm (Not yet published)
|
||||
|
||||
*(not yet published `jsonpath-wasm`)*
|
||||
```javascript
|
||||
// browser
|
||||
import * as jsonpath from "jsonpath-wasm";
|
||||
@ -56,15 +291,92 @@ import * as jsonpath from "jsonpath-wasm";
|
||||
const jsonpath = require('jsonpath-wasm');
|
||||
```
|
||||
|
||||
### jsonpath-rs library (Only NodeJS)
|
||||
##### jsonpath-rs (NodeJS only)
|
||||
|
||||
`jsonpath-rs` is native addon for NodeJs
|
||||
[Goto npmjs.org](https://www.npmjs.com/package/jsonpath-rs)
|
||||
|
||||
```javascript
|
||||
const jsonpath = require('jsonpath-rs');
|
||||
```
|
||||
|
||||
### Javascript - jsonpath.select(json: string|object, jsonpath: string)
|
||||
#### javascript - Selector class
|
||||
|
||||
##### 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 selectToObj = selector.selectTo();
|
||||
let selectToString = selector.selectToStr();
|
||||
|
||||
console.log(
|
||||
JSON.stringify(ret) == JSON.stringify(selectToObj),
|
||||
JSON.stringify(ret) == selectToString
|
||||
);
|
||||
|
||||
// => true, true
|
||||
```
|
||||
|
||||
##### jsonpath-rs
|
||||
|
||||
```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()
|
||||
.path('$..friends[0]')
|
||||
.value(jsonObj);
|
||||
|
||||
let selectToObj = selector.selectTo();
|
||||
let selectToString = selector.selectToStr();
|
||||
|
||||
console.log(
|
||||
JSON.stringify(ret) == JSON.stringify(selectToObj),
|
||||
JSON.stringify(ret) == selectToString
|
||||
);
|
||||
|
||||
// => true, true
|
||||
```
|
||||
|
||||
#### Javascript - jsonpath.select(json: string|object, jsonpath: string)
|
||||
|
||||
```javascript
|
||||
let jsonObj = {
|
||||
@ -97,7 +409,7 @@ console.log(
|
||||
// => true, true
|
||||
```
|
||||
|
||||
### Javascript - jsonpath.compile(jsonpath: string)
|
||||
#### Javascript - jsonpath.compile(jsonpath: string)
|
||||
|
||||
```javascript
|
||||
let template = jsonpath.compile('$..friends[0]');
|
||||
@ -156,7 +468,7 @@ console.log(
|
||||
// => true, true
|
||||
```
|
||||
|
||||
### Javascript - jsonpath.selector(json: string|object)
|
||||
#### Javascript - jsonpath.selector(json: string|object)
|
||||
|
||||
```javascript
|
||||
let jsonObj = {
|
||||
@ -197,13 +509,10 @@ console.log(
|
||||
// => true, true
|
||||
```
|
||||
|
||||
### Javascript - alloc_json, dealloc_json
|
||||
#### Javascript - allocJson, deallocJson (Webassembly Only)
|
||||
wasm-bindgen은 Javascript와 Webassembly간 값을 주고받을 때 JSON 객체는 String으로 변환되기 때문에, 반복해서 사용되는 JSON 객체는 Webassembly 영역에 생성해 두면 성능에 도움이 된다.
|
||||
|
||||
*(not supported in `jsonpath-rs`)*
|
||||
|
||||
wasm-bindgen은 Javascript와 Webassembly 간 값을 주고받을 때 JSON 객체는 String으로 변환되기 때문에, 반복해서 사용되는 JSON 객체를 Webassembly 영역에 생성해 두면 성능에 도움이 된다.
|
||||
|
||||
Since wasm-bindgen converts JSON objects to String when exchanging values between Javascript and Webassembly, it is helpful to create repeated Json objects in Webassembly area.
|
||||
Since wasm-bindgen converts JSON objects to String when exchanging values between Javascript and Webassembly, creating frequently used JSON objects in the WebAssembly area helps performance.
|
||||
|
||||
```javascript
|
||||
const jsonpath = require('@nodejs/jsonpath-wasm');
|
||||
@ -222,7 +531,7 @@ let jsonObj = {
|
||||
};
|
||||
|
||||
// allocate jsonObj in webassembly
|
||||
let ptr = jsonpath.alloc_json(jsonObj);
|
||||
let ptr = jsonpath.allocJson(jsonObj);
|
||||
|
||||
// `0` is invalid pointer
|
||||
if(ptr == 0) {
|
||||
@ -253,236 +562,5 @@ console.log(
|
||||
|
||||
// => true true true true true
|
||||
|
||||
jsonpath.dealloc_json(ptr);
|
||||
jsonpath.deallocJson(ptr);
|
||||
```
|
||||
|
||||
## With Rust
|
||||
|
||||
### jsonpath_lib library
|
||||
|
||||
```rust
|
||||
extern crate jsonpath_lib as jsonpath;
|
||||
#[macro_use]
|
||||
extern crate serde_json;
|
||||
```
|
||||
|
||||
### Rust - jsonpath::Selector struct
|
||||
|
||||
```rust
|
||||
#[derive(Serialize, 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_from_str(&serde_json::to_string(&json_obj).unwrap() /*&str*/).unwrap()
|
||||
// .value_from(&json_obj /*&impl serde::ser::Serialize*/).unwrap()
|
||||
.value((&json_obj /*serde_json::value::Value*/ ).into()).unwrap()
|
||||
.select_to_value().unwrap();
|
||||
|
||||
assert_eq!(json!([{"name": "친구3", "age": 30}]), result);
|
||||
|
||||
let result = selector.select_to_str().unwrap();
|
||||
assert_eq!(r#"[{"name":"친구3","age":30}]"#, result);
|
||||
|
||||
let result = selector.select_to::<Vec<Friend>>().unwrap();
|
||||
assert_eq!(vec![Friend { name: "친구3".to_string(), age: Some(30) }], result);
|
||||
```
|
||||
|
||||
### 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();
|
||||
|
||||
let ret = json!([
|
||||
{"name": "친구3", "age": 30},
|
||||
{"name": "친구1", "age": 20}
|
||||
]);
|
||||
assert_eq!(json, ret);
|
||||
```
|
||||
|
||||
### Rust - jsonpath::select_as_str(json: &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, jsonpath: &str)
|
||||
|
||||
```rust
|
||||
#[derive(Deserialize, PartialEq, Debug)]
|
||||
struct Person {
|
||||
name: String,
|
||||
age: u8,
|
||||
phones: Vec<String>,
|
||||
}
|
||||
|
||||
let ret: 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!(person, ret);
|
||||
```
|
||||
|
||||
### Rust - jsonpath::compile(jsonpath: &str)
|
||||
|
||||
```rust
|
||||
let mut template = jsonpath::compile("$..friends[0]");
|
||||
|
||||
let json_obj = json!({
|
||||
"school": {
|
||||
"friends": [
|
||||
{"name": "친구1", "age": 20},
|
||||
{"name": "친구2", "age": 20}
|
||||
]
|
||||
},
|
||||
"friends": [
|
||||
{"name": "친구3", "age": 30},
|
||||
{"name": "친구4"}
|
||||
]});
|
||||
|
||||
let json = template(&json_obj).unwrap();
|
||||
|
||||
let ret = json!([
|
||||
{"name": "친구3", "age": 30},
|
||||
{"name": "친구1", "age": 20}
|
||||
]);
|
||||
|
||||
assert_eq!(json, ret);
|
||||
```
|
||||
|
||||
### 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();
|
||||
|
||||
let ret = json!([
|
||||
{"name": "친구3", "age": 30},
|
||||
{"name": "친구1", "age": 20}
|
||||
]);
|
||||
|
||||
assert_eq!(json, ret);
|
||||
|
||||
let json = selector("$..friends[1]").unwrap();
|
||||
|
||||
let ret = json!([
|
||||
{"name": "친구4"},
|
||||
{"name": "친구2", "age": 20}
|
||||
]);
|
||||
|
||||
assert_eq!(json, ret);
|
||||
```
|
||||
|
||||
### 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(Serialize, Deserialize, PartialEq, Debug)]
|
||||
struct Friend {
|
||||
name: String,
|
||||
age: Option<u8>,
|
||||
}
|
||||
|
||||
let mut selector = jsonpath::selector_as::<Vec<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);
|
||||
```
|
@ -37,6 +37,8 @@ __extra () {
|
||||
printf "\n"
|
||||
sleep 1
|
||||
cd "${DIR}"/javascript && echo "NodeJs - jsonpath-wasm - compile-alloc: " && time ./bench.sh wasmCompileAlloc ${ITER}
|
||||
sleep 1
|
||||
cd "${DIR}"/javascript && echo "NodeJs - jsonpath-wasm - Selector: " && time ./bench.sh wasmSelectorClass ${ITER}
|
||||
}
|
||||
|
||||
if [ "$1" = "extra" ]; then
|
||||
|
@ -86,7 +86,7 @@ function wasmCompile() {
|
||||
}
|
||||
|
||||
function wasmCompileAlloc() {
|
||||
let ptr = jpw.alloc_json(getJson());
|
||||
let ptr = jpw.allocJson(getJson());
|
||||
if (ptr == 0) {
|
||||
console.error('Invalid pointer');
|
||||
return;
|
||||
@ -98,7 +98,7 @@ function wasmCompileAlloc() {
|
||||
let _ = template(ptr);
|
||||
}
|
||||
} finally {
|
||||
jpw.dealloc_json(ptr);
|
||||
jpw.deallocJson(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,7 +109,7 @@ function wasmSelect() {
|
||||
}
|
||||
|
||||
function wasmSelectAlloc() {
|
||||
let ptr = jpw.alloc_json(getJson());
|
||||
let ptr = jpw.allocJson(getJson());
|
||||
if (ptr == 0) {
|
||||
console.error('Invalid pointer');
|
||||
return;
|
||||
@ -120,7 +120,16 @@ function wasmSelectAlloc() {
|
||||
let _ = jpw.select(ptr, path);
|
||||
}
|
||||
} finally {
|
||||
jpw.dealloc_json(ptr);
|
||||
jpw.deallocJson(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
function wasmSelectorClass() {
|
||||
let selector = new jpw.Selector();
|
||||
for (var i = 0; i < iter; i++) {
|
||||
selector.path(path);
|
||||
selector.value(jsonStr);
|
||||
let _ = selector.selectToStr();
|
||||
}
|
||||
}
|
||||
|
||||
|
4
build.sh
4
build.sh
@ -54,11 +54,11 @@ echo
|
||||
echo
|
||||
__msg "wasm-pack"
|
||||
cd "${WASM}" && \
|
||||
wasm-pack build --target=nodejs --scope nodejs --out-dir nodejs_pkg && \
|
||||
wasm-pack build --release --target=nodejs --scope nodejs --out-dir nodejs_pkg && \
|
||||
cd "${WASM_NODEJS_PKG}" && npm link
|
||||
|
||||
cd "${WASM}" && \
|
||||
wasm-pack build --target=browser --scope browser --out-dir browser_pkg && \
|
||||
wasm-pack build --release --target=browser --scope browser --out-dir browser_pkg && \
|
||||
cd "${WASM_BROWSER_PKG}" && npm link
|
||||
|
||||
echo
|
||||
|
File diff suppressed because one or more lines are too long
Binary file not shown.
BIN
docs/68fa958468b8cdcb12e4.module.wasm
Normal file
BIN
docs/68fa958468b8cdcb12e4.module.wasm
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
BIN
docs/bench/68fa958468b8cdcb12e4.module.wasm
Normal file
BIN
docs/bench/68fa958468b8cdcb12e4.module.wasm
Normal file
Binary file not shown.
13
docs/bench/bootstrap.js
vendored
13
docs/bench/bootstrap.js
vendored
@ -88,11 +88,14 @@
|
||||
/******/ "__wbindgen_throw": function(p0i32,p1i32) {
|
||||
/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_throw"](p0i32,p1i32);
|
||||
/******/ },
|
||||
/******/ "__wbindgen_closure_wrapper77": function(p0i32,p1i32,p2i32) {
|
||||
/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper77"](p0i32,p1i32,p2i32);
|
||||
/******/ "__wbindgen_rethrow": function(p0i32) {
|
||||
/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_rethrow"](p0i32);
|
||||
/******/ },
|
||||
/******/ "__wbindgen_closure_wrapper79": function(p0i32,p1i32,p2i32) {
|
||||
/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper79"](p0i32,p1i32,p2i32);
|
||||
/******/ "__wbindgen_closure_wrapper103": function(p0i32,p1i32,p2i32) {
|
||||
/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper103"](p0i32,p1i32,p2i32);
|
||||
/******/ },
|
||||
/******/ "__wbindgen_closure_wrapper105": function(p0i32,p1i32,p2i32) {
|
||||
/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper105"](p0i32,p1i32,p2i32);
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/ };
|
||||
@ -192,7 +195,7 @@
|
||||
/******/ promises.push(installedWasmModuleData);
|
||||
/******/ else {
|
||||
/******/ var importObject = wasmImportObjects[wasmModuleId]();
|
||||
/******/ var req = fetch(__webpack_require__.p + "" + {"../browser_pkg/jsonpath_wasm_bg.wasm":"215c5418dd8b4be64f60"}[wasmModuleId] + ".module.wasm");
|
||||
/******/ var req = fetch(__webpack_require__.p + "" + {"../browser_pkg/jsonpath_wasm_bg.wasm":"68fa958468b8cdcb12e4"}[wasmModuleId] + ".module.wasm");
|
||||
/******/ var promise;
|
||||
/******/ if(importObject instanceof Promise && typeof WebAssembly.compileStreaming === 'function') {
|
||||
/******/ promise = Promise.all([WebAssembly.compileStreaming(req), importObject]).then(function(items) {
|
||||
|
13
docs/bootstrap.js
vendored
13
docs/bootstrap.js
vendored
@ -88,11 +88,14 @@
|
||||
/******/ "__wbindgen_throw": function(p0i32,p1i32) {
|
||||
/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_throw"](p0i32,p1i32);
|
||||
/******/ },
|
||||
/******/ "__wbindgen_closure_wrapper77": function(p0i32,p1i32,p2i32) {
|
||||
/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper77"](p0i32,p1i32,p2i32);
|
||||
/******/ "__wbindgen_rethrow": function(p0i32) {
|
||||
/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_rethrow"](p0i32);
|
||||
/******/ },
|
||||
/******/ "__wbindgen_closure_wrapper79": function(p0i32,p1i32,p2i32) {
|
||||
/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper79"](p0i32,p1i32,p2i32);
|
||||
/******/ "__wbindgen_closure_wrapper103": function(p0i32,p1i32,p2i32) {
|
||||
/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper103"](p0i32,p1i32,p2i32);
|
||||
/******/ },
|
||||
/******/ "__wbindgen_closure_wrapper105": function(p0i32,p1i32,p2i32) {
|
||||
/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper105"](p0i32,p1i32,p2i32);
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/ };
|
||||
@ -192,7 +195,7 @@
|
||||
/******/ promises.push(installedWasmModuleData);
|
||||
/******/ else {
|
||||
/******/ var importObject = wasmImportObjects[wasmModuleId]();
|
||||
/******/ var req = fetch(__webpack_require__.p + "" + {"../browser_pkg/jsonpath_wasm_bg.wasm":"215c5418dd8b4be64f60"}[wasmModuleId] + ".module.wasm");
|
||||
/******/ var req = fetch(__webpack_require__.p + "" + {"../browser_pkg/jsonpath_wasm_bg.wasm":"68fa958468b8cdcb12e4"}[wasmModuleId] + ".module.wasm");
|
||||
/******/ var promise;
|
||||
/******/ if(importObject instanceof Promise && typeof WebAssembly.compileStreaming === 'function') {
|
||||
/******/ promise = Promise.all([WebAssembly.compileStreaming(req), importObject]).then(function(items) {
|
||||
|
2
nodejs/package-lock.json
generated
2
nodejs/package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jsonpath-rs",
|
||||
"version": "0.1.6",
|
||||
"version": "0.1.7",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "jsonpath-wasm"
|
||||
name = "jsonpath_wasm"
|
||||
version = "0.1.7"
|
||||
authors = ["Changseok Han <freestrings@gmail.com>"]
|
||||
description = "JsonPath Webassembly version compiled by Rust - Demo: https://freestrings.github.io/jsonpath"
|
||||
@ -26,6 +26,9 @@ web-sys = { version = "0.3", features = ['console'] }
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen-test = "0.2"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
js-sys = "0.3"
|
||||
|
||||
[profile.release]
|
||||
opt-level = "s"
|
||||
|
@ -7,17 +7,19 @@ extern crate wasm_bindgen;
|
||||
extern crate web_sys;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::ops::Deref;
|
||||
use std::result::Result;
|
||||
use std::sync::Mutex;
|
||||
use std::ops::Deref;
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use web_sys::console;
|
||||
|
||||
use jsonpath::filter::value_filter::JsonValueFilter;
|
||||
use jsonpath::parser::parser::{Node, NodeVisitor, Parser};
|
||||
use jsonpath::ref_value::model::{RefValue, RefValueWrapper};
|
||||
use jsonpath::Selector as _Selector;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use web_sys::console;
|
||||
|
||||
use std::result;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "wee_alloc")] {
|
||||
@ -85,8 +87,8 @@ lazy_static! {
|
||||
static ref CACHE_JSON_IDX: Mutex<usize> = Mutex::new(0);
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn alloc_json(js_value: JsValue) -> usize {
|
||||
#[wasm_bindgen(js_name = allocJson)]
|
||||
pub extern fn alloc_json(js_value: JsValue) -> usize {
|
||||
match into_serde_json(&js_value) {
|
||||
Ok(json) => {
|
||||
let mut map = CACHE_JSON.lock().unwrap();
|
||||
@ -106,8 +108,8 @@ pub fn alloc_json(js_value: JsValue) -> usize {
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn dealloc_json(ptr: usize) -> bool {
|
||||
#[wasm_bindgen(js_name = deallocJson)]
|
||||
pub extern fn dealloc_json(ptr: usize) -> bool {
|
||||
let mut map = CACHE_JSON.lock().unwrap();
|
||||
map.remove(&ptr).is_some()
|
||||
}
|
||||
@ -167,5 +169,49 @@ pub fn select(js_value: JsValue, path: &str) -> JsValue {
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// `wasm_bindgen` 제약으로 builder-pattern을 구사 할 수 없다.
|
||||
///
|
||||
#[wasm_bindgen]
|
||||
pub struct Selector {
|
||||
selector: _Selector
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl Selector {
|
||||
|
||||
#[wasm_bindgen(constructor)]
|
||||
pub fn new() -> Self {
|
||||
Selector { selector: _Selector::new() }
|
||||
}
|
||||
|
||||
#[wasm_bindgen(catch)]
|
||||
pub fn path(&mut self, path: &str) -> result::Result<(), JsValue> {
|
||||
let _ = self.selector.path(path)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[wasm_bindgen(catch)]
|
||||
pub fn value(&mut self, value: JsValue) -> result::Result<(), JsValue> {
|
||||
let ref_value = into_serde_json(&value)?;
|
||||
let _ = self.selector.value(ref_value)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[wasm_bindgen(catch, js_name = selectToStr)]
|
||||
pub fn select_to_str(&mut self) -> result::Result<JsValue, JsValue> {
|
||||
let json_str = self.selector.select_to_str()?;
|
||||
Ok(JsValue::from_str(&json_str))
|
||||
}
|
||||
|
||||
#[wasm_bindgen(catch, js_name = selectTo)]
|
||||
pub fn select_to(&mut self) -> result::Result<JsValue, JsValue> {
|
||||
let ref_value = self.selector.select_to::<RefValue>()
|
||||
.map_err(|e| JsValue::from_str(&e))?;
|
||||
Ok(JsValue::from_serde(&ref_value)
|
||||
.map_err(|e| JsValue::from_str(&format!("{:?}", e)))?)
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn testa() {}
|
@ -1,13 +1,118 @@
|
||||
//! Test suite for the Web and headless browsers.
|
||||
|
||||
#![cfg(target_arch = "wasm32")]
|
||||
|
||||
extern crate core;
|
||||
extern crate js_sys;
|
||||
extern crate jsonpath_wasm as jsonpath;
|
||||
#[macro_use]
|
||||
extern crate serde_json;
|
||||
extern crate wasm_bindgen;
|
||||
extern crate wasm_bindgen_test;
|
||||
|
||||
use serde_json::Value;
|
||||
use wasm_bindgen::*;
|
||||
use wasm_bindgen_test::*;
|
||||
|
||||
wasm_bindgen_test_configure!(run_in_browser);
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn pass() {
|
||||
assert_eq!(1 + 1, 2);
|
||||
fn json_str() -> &'static str {
|
||||
r#"
|
||||
{
|
||||
"store": {
|
||||
"book": [
|
||||
{
|
||||
"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": "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
|
||||
}
|
||||
],
|
||||
"bicycle": {
|
||||
"color": "red",
|
||||
"price": 19.95
|
||||
}
|
||||
},
|
||||
"expensive": 10
|
||||
}
|
||||
"#
|
||||
}
|
||||
|
||||
fn target_json() -> Value {
|
||||
json!([{
|
||||
"category" : "fiction",
|
||||
"author" : "Herman Melville",
|
||||
"title" : "Moby Dick",
|
||||
"isbn" : "0-553-21311-3",
|
||||
"price" : 8.99
|
||||
}])
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn select() {
|
||||
let json: Value = jsonpath::select(JsValue::from_str(json_str()), "$..book[2]").into_serde().unwrap();
|
||||
assert_eq!(json, target_json());
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn compile() {
|
||||
let js_value = jsonpath::compile("$..book[2]");
|
||||
assert_eq!(js_value.is_function(), true);
|
||||
|
||||
let cb: &js_sys::Function = JsCast::unchecked_ref(js_value.as_ref());
|
||||
let cb_result: JsValue = cb.call1(&js_value, &JsValue::from_str(json_str())).unwrap();
|
||||
let json: Value = cb_result.into_serde().unwrap();
|
||||
assert_eq!(json, target_json());
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn selector() {
|
||||
let js_value = jsonpath::selector(JsValue::from_str(json_str()));
|
||||
assert_eq!(js_value.is_function(), true);
|
||||
|
||||
let cb: &js_sys::Function = JsCast::unchecked_ref(js_value.as_ref());
|
||||
let cb_result: JsValue = cb.call1(&js_value, &JsValue::from_str("$..book[2]")).unwrap();
|
||||
let json: Value = cb_result.into_serde().unwrap();
|
||||
assert_eq!(json, target_json());
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn alloc_dealloc_json() {
|
||||
let ptr = jsonpath::alloc_json(JsValue::from_str(json_str()));
|
||||
assert_eq!(ptr > 0, true);
|
||||
|
||||
let json: Value = jsonpath::select(JsValue::from_f64(ptr as f64), "$..book[2]").into_serde().unwrap();
|
||||
assert_eq!(json, target_json());
|
||||
|
||||
assert_eq!(jsonpath::dealloc_json(ptr), true);
|
||||
|
||||
let err = jsonpath::select(JsValue::from_f64(ptr as f64), "$..book[2]").as_string().unwrap();
|
||||
assert_eq!(err, "Invalid pointer".to_string());
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn selector_struct() {
|
||||
let mut selector = jsonpath::Selector::new();
|
||||
selector.path("$..book[2]").unwrap();
|
||||
selector.value(JsValue::from_str(json_str())).unwrap();
|
||||
let json: Value = selector.select_to().unwrap().into_serde().unwrap();
|
||||
assert_eq!(json, target_json());
|
||||
}
|
@ -61,7 +61,7 @@ let path = '$..book[?(@.price<30 && @.category=="fiction")]';
|
||||
let template = jpw.compile(path);
|
||||
let selector = jpw.selector(json);
|
||||
|
||||
let ptr = jpw.alloc_json(json);
|
||||
let ptr = jpw.allocJson(json);
|
||||
if(ptr == 0) console.error('invalid ptr');
|
||||
|
||||
let iterCount = 2000;
|
||||
@ -83,7 +83,7 @@ run('jsonpath', iterCount, function() { jp.query(json, path) })
|
||||
return run('jsonpath-wasm- select-alloc', iterCount, function() { jpw.select(ptr, path) });
|
||||
})
|
||||
.finally(function() {
|
||||
if(!jpw.dealloc_json(ptr)) {
|
||||
if(!jpw.deallocJson(ptr)) {
|
||||
console.error('fail to dealloc');
|
||||
}
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user