• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

.idea/runConfigurations/H08-Dec-2021-3939

benchmark/H08-Dec-2021-5,1935,132

docs/H03-May-2022-3737

lua/H08-Dec-2021-312232

src/H08-Dec-2021-4,8553,670

tests/H08-Dec-2021-2,3832,045

wasm/H08-Dec-2021-12,48212,317

.gitignoreH A D08-Dec-202177 66

.travis.ymlH A D08-Dec-20211.6 KiB6966

Cargo.tomlH A D08-Dec-20211,001 3628

LICENSEH A D08-Dec-20211 KiB2117

README.mdH A D08-Dec-202115.3 KiB698552

bench.shH A D08-Dec-2021102 102

build-wasm.shH A D08-Dec-20212 KiB9172

clippy.shH A D08-Dec-2021296 118

coverage.shH A D08-Dec-2021132 92

profiling.shH A D08-Dec-2021145 96

README.md

1# jsonpath_lib
2
3[![Build Status](https://travis-ci.org/freestrings/jsonpath.svg?branch=master)](https://travis-ci.org/freestrings/jsonpath)
4![crates.io](https://img.shields.io/crates/v/jsonpath_lib.svg)
5![npm](https://img.shields.io/npm/v/jsonpath-wasm.svg?label=npm%20%60jsonpath-wasm%60)
6![Codecov](https://img.shields.io/codecov/c/github/freestrings/jsonpath.svg?token=92c41b4e7cf04a9cbebc08f68c5da615)
7
8`Rust` 버전 [JsonPath](https://goessner.net/articles/JsonPath/) 구현으로 `Webassembly`와 `Javascript`에서도 유사한 API 인터페이스를 제공 한다.
9
10It is JsonPath [JsonPath](https://goessner.net/articles/JsonPath/) engine written in `Rust`. it provide a similar API interface in `Webassembly` and` Javascript` too.
11
12- [Webassembly Demo](https://freestrings.github.io/jsonpath/)
13- [NPM jsonpath-wasm - webassembly](https://www.npmjs.com/package/jsonpath-wasm)
14
15## Rust API
16
17<details><summary><b>jsonpath_lib crate</b></summary>
18
19Go to [`jsonpath_lib` creates.io](https://crates.io/crates/jsonpath_lib)
20
21```rust
22extern crate jsonpath_lib as jsonpath;
23```
24
25</details>
26
27<details><summary><b>Rust - jsonpath::Selector struct</b></summary>
28
29```rust
30#[derive(Deserialize, PartialEq, Debug)]
31struct Friend {
32    name: String,
33    age: Option<u8>,
34}
35
36let json_obj = json!({
37    "school": {
38        "friends": [
39            {"name": "친구1", "age": 20},
40            {"name": "친구2", "age": 20}
41        ]
42    },
43    "friends": [
44        {"name": "친구3", "age": 30},
45        {"name": "친구4"}
46]});
47
48let mut selector = Selector::new();
49
50let result = selector
51    .path("$..[?(@.age >= 30)]").unwrap()
52    .value(&json_obj)
53    .select().unwrap();
54
55assert_eq!(vec![&json!({"name": "친구3", "age": 30})], result);
56
57let result = selector.select_as_str().unwrap();
58assert_eq!(r#"[{"name":"친구3","age":30}]"#, result);
59
60let result = selector.select_as::<Friend>().unwrap();
61assert_eq!(vec![Friend { name: "친구3".to_string(), age: Some(30) }], result);
62```
63
64</details>
65
66<details><summary><b>Rust - jsonpath::SelectorMut struct</b></summary>
67
68```rust
69let json_obj = json!({
70    "school": {
71        "friends": [
72            {"name": "친구1", "age": 20},
73            {"name": "친구2", "age": 20}
74        ]
75    },
76    "friends": [
77        {"name": "친구3", "age": 30},
78        {"name": "친구4"}
79]});
80
81let mut selector_mut = SelectorMut::new();
82
83let result = selector_mut
84    .str_path("$..[?(@.age == 20)].age").unwrap()
85    .value(json_obj)
86    .replace_with(&mut |v| {
87        let age = if let Value::Number(n) = v {
88            n.as_u64().unwrap() * 2
89        } else {
90            0
91        };
92
93        Some(json!(age))
94    }).unwrap()
95    .take().unwrap();
96
97assert_eq!(result, json!({
98    "school": {
99        "friends": [
100            {"name": "친구1", "age": 40},
101            {"name": "친구2", "age": 40}
102        ]
103    },
104    "friends": [
105        {"name": "친구3", "age": 30},
106        {"name": "친구4"}
107]}));
108```
109
110</details>
111
112<details><summary><b>Rust - jsonpath::select(json: &serde_json::value::Value, jsonpath: &str)</b></summary>
113
114```rust
115let json_obj = json!({
116    "school": {
117        "friends": [
118            {"name": "친구1", "age": 20},
119            {"name": "친구2", "age": 20}
120        ]
121    },
122    "friends": [
123        {"name": "친구3", "age": 30},
124        {"name": "친구4"}
125]});
126
127let json = jsonpath::select(&json_obj, "$..friends[0]").unwrap();
128
129assert_eq!(json, vec![
130    &json!({"name": "친구3", "age": 30}),
131    &json!({"name": "친구1", "age": 20})
132]);
133```
134
135</details>
136
137
138<details><summary><b>Rust - jsonpath::select_as_str(json_str: &str, jsonpath: &str)</b></summary>
139
140```rust
141let ret = jsonpath::select_as_str(r#"
142{
143    "school": {
144        "friends": [
145                {"name": "친구1", "age": 20},
146                {"name": "친구2", "age": 20}
147            ]
148    },
149    "friends": [
150        {"name": "친구3", "age": 30},
151        {"name": "친구4"}
152    ]
153}
154"#, "$..friends[0]").unwrap();
155
156assert_eq!(ret, r#"[{"name":"친구3","age":30},{"name":"친구1","age":20}]"#);
157```
158
159</details>
160
161<details><summary><b>Rust - jsonpath::select_as&lt;T: `serde::de::DeserializeOwned`&gt;(json_str: &str, jsonpath: &str)</b></summary>
162
163```rust
164#[derive(Deserialize, PartialEq, Debug)]
165struct Person {
166    name: String,
167    age: u8,
168    phones: Vec<String>,
169}
170
171let ret: Vec<Person> = jsonpath::select_as(r#"
172{
173    "person":
174        {
175            "name": "Doe John",
176            "age": 44,
177            "phones": [
178                "+44 1234567",
179                "+44 2345678"
180            ]
181        }
182}
183"#, "$.person").unwrap();
184
185let person = Person {
186    name: "Doe John".to_string(),
187    age: 44,
188    phones: vec!["+44 1234567".to_string(), "+44 2345678".to_string()],
189};
190
191assert_eq!(ret[0], person);
192```
193
194</details>
195
196<details><summary><b>Rust - jsonpath::Compiled::compile(jsonpath: &str)</b></summary>
197
198```rust
199let template = jsonpath::Compiled::compile("$..friends[0]").unwrap();
200
201let json_obj = json!({
202    "school": {
203        "friends": [
204            {"name": "친구1", "age": 20},
205            {"name": "친구2", "age": 20}
206        ]
207    },
208    "friends": [
209        {"name": "친구3", "age": 30},
210        {"name": "친구4"}
211]});
212
213let json = template.select(&json_obj).unwrap();
214
215assert_eq!(json, vec![
216    &json!({"name": "친구3", "age": 30}),
217    &json!({"name": "친구1", "age": 20})
218]);
219```
220
221</details>
222
223<details><summary><b>Rust - jsonpath::selector(json: &serde_json::value::Value)</b></summary>
224
225```rust
226let json_obj = json!({
227    "school": {
228        "friends": [
229            {"name": "친구1", "age": 20},
230            {"name": "친구2", "age": 20}
231        ]
232    },
233    "friends": [
234        {"name": "친구3", "age": 30},
235        {"name": "친구4"}
236]});
237
238let mut selector = jsonpath::selector(&json_obj);
239
240let json = selector("$..friends[0]").unwrap();
241
242assert_eq!(json, vec![
243    &json!({"name": "친구3", "age": 30}),
244    &json!({"name": "친구1", "age": 20})
245]);
246
247let json = selector("$..friends[1]").unwrap();
248
249assert_eq!(json, vec![
250    &json!({"name": "친구4"}),
251    &json!({"name": "친구2", "age": 20})
252]);
253```
254
255</details>
256
257<details><summary><b>Rust - jsonpath::selector_as&lt;T: serde::de::DeserializeOwned&gt;(json: &serde_json::value::Value)</b></summary>
258
259```rust
260let json_obj = json!({
261    "school": {
262       "friends": [
263            {"name": "친구1", "age": 20},
264            {"name": "친구2", "age": 20}
265        ]
266    },
267    "friends": [
268        {"name": "친구3", "age": 30},
269        {"name": "친구4"}
270]});
271
272#[derive(Deserialize, PartialEq, Debug)]
273struct Friend {
274    name: String,
275    age: Option<u8>,
276}
277
278let mut selector = jsonpath::selector_as::<Friend>(&json_obj);
279
280let json = selector("$..friends[0]").unwrap();
281
282let ret = vec!(
283    Friend { name: "친구3".to_string(), age: Some(30) },
284    Friend { name: "친구1".to_string(), age: Some(20) }
285);
286assert_eq!(json, ret);
287
288let json = selector("$..friends[1]").unwrap();
289
290let ret = vec!(
291    Friend { name: "친구4".to_string(), age: None },
292    Friend { name: "친구2".to_string(), age: Some(20) }
293);
294
295assert_eq!(json, ret);
296```
297
298</details>
299
300<details><summary><b>Rust - jsonpath::delete(value: &Value, path: &str)</b></summary>
301
302```rust
303let json_obj = json!({
304    "school": {
305        "friends": [
306            {"name": "친구1", "age": 20},
307            {"name": "친구2", "age": 20}
308        ]
309    },
310    "friends": [
311        {"name": "친구3", "age": 30},
312        {"name": "친구4"}
313]});
314
315let ret = jsonpath::delete(json_obj, "$..[?(20 == @.age)]").unwrap();
316
317assert_eq!(ret, json!({
318    "school": {
319        "friends": [
320            null,
321            null
322        ]
323    },
324    "friends": [
325        {"name": "친구3", "age": 30},
326        {"name": "친구4"}
327]}));
328```
329
330</details>
331
332<details><summary><b>Rust - jsonpath::replace_with&lt;F: FnMut(&Value) -> Value&gt;(value: &Value, path: &str, fun: &mut F)</b></summary>
333
334```rust
335let json_obj = json!({
336    "school": {
337        "friends": [
338            {"name": "친구1", "age": 20},
339            {"name": "친구2", "age": 20}
340        ]
341    },
342    "friends": [
343        {"name": "친구3", "age": 30},
344        {"name": "친구4"}
345]});
346
347let ret = jsonpath::replace_with(json_obj, "$..[?(@.age == 20)].age", &mut |v| {
348    let age = if let Value::Number(n) = v {
349        n.as_u64().unwrap() * 2
350    } else {
351        0
352    };
353
354    Some(json!(age))
355}).unwrap();
356
357assert_eq!(ret, json!({
358    "school": {
359        "friends": [
360            {"name": "친구1", "age": 40},
361            {"name": "친구2", "age": 40}
362        ]
363    },
364    "friends": [
365        {"name": "친구3", "age": 30},
366        {"name": "친구4"}
367]}));
368```
369
370</details>
371
372[Rust - Other Examples](https://github.com/freestrings/jsonpath/wiki/rust-examples)
373
374## Javascript API
375
376<details><summary><b>npm package</b></summary>
377
378##### jsonpath-wasm
379
380Goto [`jsonpath-wasm` npmjs.org](https://www.npmjs.com/package/jsonpath-wasm)
381
382```javascript
383// browser
384import * as jsonpath from "jsonpath-wasm";
385// NodeJs
386const jsonpath = require('jsonpath-wasm');
387```
388
389##### jsonpath-wasm
390`wasm-bindgen` 리턴 타입 제약 때문에 빌더 패턴은 지원하지 않는다.
391
392It does not support `builder-pattern` due to the `return type` restriction of `wasm-bindgen`.
393
394```javascript
395let jsonObj = {
396    "school": {
397        "friends": [
398            {"name": "친구1", "age": 20},
399            {"name": "친구2", "age": 20}
400        ]
401    },
402    "friends": [
403        {"name": "친구3", "age": 30},
404        {"name": "친구4"}
405    ]
406};
407
408let ret = [
409    {"name": "친구3", "age": 30},
410    {"name": "친구1", "age": 20}
411];
412
413let selector = new jsonpath.Selector();
414selector.path('$..friends[0]');
415selector.value(jsonObj);
416
417let retObj = selector.select();
418
419console.log(JSON.stringify(ret) == JSON.stringify(retObj));
420
421// => true
422```
423
424빌더 패턴 제약은 `Selector class`와 동일하다.
425
426```javascript
427let jsonObj = {
428    'school': {
429        'friends': [
430            {'name': '친구1', 'age': 20},
431            {'name': '친구2', 'age': 20},
432        ],
433    },
434    'friends': [
435        {'name': '친구3', 'age': 30},
436        {'name': '친구4'},
437    ],
438};
439
440let selector = new jsonpath.SelectorMut();
441selector.path('$..[?(@.age == 20)]');
442
443{
444    selector.value(jsonObj);
445    selector.deleteValue();
446
447    let resultObj = {
448        'school': {'friends': [null, null]},
449        'friends': [
450            {'name': '친구3', 'age': 30},
451            {'name': '친구4'},
452        ],
453    };
454    console.log(JSON.stringify(selector.take()) !== JSON.stringify(resultObj));
455
456    // => true
457}
458
459{
460    selector.value(jsonObj);
461    selector.replaceWith((v) => {
462        v.age = v.age * 2;
463        return v;
464    });
465
466    let resultObj = {
467        'school': {
468            'friends': [
469                {'name': '친구1', 'age': 40},
470                {'name': '친구2', 'age': 40},
471            ],
472        },
473        'friends': [
474            {'name': '친구3', 'age': 30},
475            {'name': '친구4'},
476        ],
477    };
478    console.log(JSON.stringify(selector.take()) !== JSON.stringify(resultObj));
479
480    // => true
481}
482```
483
484</details>
485
486<details><summary><b>Javascript - jsonpath.select(json: string|object, jsonpath: string)</b></summary>
487
488```javascript
489let jsonObj = {
490    "school": {
491        "friends": [
492            {"name": "친구1", "age": 20},
493            {"name": "친구2", "age": 20}
494        ]
495    },
496    "friends": [
497        {"name": "친구3", "age": 30},
498        {"name": "친구4"}
499    ]
500};
501
502let ret = [
503    {"name": "친구3", "age": 30},
504    {"name": "친구1", "age": 20}
505];
506
507
508let selectAsString = jsonpath.select(JSON.stringify(jsonObj), '$..friends[0]');
509let selectAsObj = jsonpath.select(jsonObj, '$..friends[0]');
510
511console.log(
512    JSON.stringify(ret) == JSON.stringify(selectAsString),
513    JSON.stringify(ret) == JSON.stringify(selectAsObj)
514);
515
516// => true, true
517```
518
519</details>
520
521<details><summary><b>Javascript - jsonpath.compile(jsonpath: string)</b></summary>
522
523```javascript
524let error = jsonpath.compile('');
525console.log(typeof error, error); //string 'path error'
526
527let template = jsonpath.compile('$..friends[0]');
528
529let jsonObj = {
530    "school": {
531        "friends": [
532            {"name": "친구1", "age": 20},
533            {"name": "친구2", "age": 20}
534        ]
535    },
536    "friends": [
537        {"name": "친구3", "age": 30},
538        {"name": "친구4"}
539    ]
540};
541
542let ret = [
543    {"name": "친구3", "age": 30},
544    {"name": "친구1", "age": 20}
545];
546
547let selectAsString = template(JSON.stringify(jsonObj));
548let selectAsObj = template(jsonObj);
549
550console.log(
551    JSON.stringify(ret) == JSON.stringify(selectAsString),
552    JSON.stringify(ret) == JSON.stringify(selectAsObj)
553);
554
555// => true, true
556
557let jsonObj2 = {
558    "school": {
559        "friends": [
560            {"name": "Millicent Norman"},
561            {"name": "Vincent Cannon"}
562        ]
563    },
564    "friends": [ {"age": 30}, {"age": 40} ]
565};
566
567let ret2 = [
568    {"age": 30},
569    {"name": "Millicent Norman"}
570];
571
572let selectAsString2 = template(JSON.stringify(jsonObj2));
573let selectAsObj2 = template(jsonObj2);
574
575console.log(
576        JSON.stringify(ret2) == JSON.stringify(selectAsString2),
577        JSON.stringify(ret2) == JSON.stringify(selectAsObj2)
578);
579
580// => true, true
581```
582
583</details>
584
585<details><summary><b>Javascript - jsonpath.selector(json: string|object)</b></summary>
586
587```javascript
588let jsonObj = {
589    "school": {
590        "friends": [
591            {"name": "친구1", "age": 20},
592            {"name": "친구2", "age": 20}
593        ]
594    },
595    "friends": [
596        {"name": "친구3", "age": 30},
597        {"name": "친구4"}
598    ]
599};
600
601let ret1 = [
602    {"name": "친구3", "age": 30},
603    {"name": "친구1", "age": 20}
604];
605
606let ret2 = [
607    {"name": "친구4"},
608    {"name": "친구2", "age": 20}
609];
610
611let selector = jsonpath.selector(jsonObj);
612// or as json string
613// let selector = jsonpath.selector(JSON.stringify(jsonObj));
614
615let select1 = selector('$..friends[0]');
616let select2 = selector('$..friends[1]');
617
618console.log(
619    JSON.stringify(ret1) == JSON.stringify(select1),
620    JSON.stringify(ret2) == JSON.stringify(select2)
621);
622
623// => true, true
624```
625
626</details>
627
628<details><summary><b>Javascript - jsonpath.deleteValue(json: string|object, path: string)</b></summary>
629
630```javascript
631let jsonObj = {
632    "school": {
633        "friends": [
634            {"name": "친구1", "age": 20},
635            {"name": "친구2", "age": 20}
636        ]
637    },
638    "friends": [
639        {"name": "친구3", "age": 30},
640        {"name": "친구4"}
641    ]
642};
643
644let _1 = jsonpath.deleteValue(jsonObj, '$..friends[0]');
645let result = jsonpath.deleteValue(_1, '$..friends[1]');
646
647console.log(JSON.stringify(result) !== JSON.stringify({
648    "school": { "friends": [null, null]},
649    "friends": [null, null]
650}));
651
652// => true
653
654```
655
656</details>
657
658<details><summary><b>Javascript - jsonpath.replaceWith(json: string|object, path: string, fun: function(json: object) => json: object</b></summary>
659
660```javascript
661let jsonObj = {
662    "school": {
663        "friends": [
664            {"name": "친구1", "age": 20},
665            {"name": "친구2", "age": 20}
666        ]
667    },
668    "friends": [
669        {"name": "친구3", "age": 30},
670        {"name": "친구4"}
671    ]
672};
673
674let result = jsonpath.replaceWith(jsonObj, '$..friends[0]', (v) => {
675    v.age = v.age * 2;
676    return v;
677});
678
679console.log(JSON.stringify(result) === JSON.stringify({
680    "school": {
681        "friends": [
682            {"name": "친구1", "age": 40},
683            {"name": "친구2", "age": 20}
684        ]
685    },
686    "friends": [
687        {"name": "친구3", "age": 60},
688        {"name": "친구4"}
689    ]
690}));
691
692// => true
693
694```
695
696</details>
697
698[Javascript - Other Examples](https://github.com/freestrings/jsonpath/wiki/Javascript-examples)