1- <!-- START doctoc generated TOC please keep comment here to allow auto update -->
2- <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
3-
41- [ jsonpath-python] ( #jsonpath-python )
52 - [ Features] ( #features )
6- - [ Examples] ( #examples )
7- - [ Filter] ( #filter )
8- - [ Sorter] ( #sorter )
9- - [ Field-Extractor] ( #field-extractor )
10-
11- <!-- END doctoc generated TOC please keep comment here to allow auto update -->
3+ - [ JSONPath Syntax] ( #jsonpath-syntax )
4+ - [ Operators] ( #operators )
5+ - [ Examples] ( #examples )
6+ - [ Select Fields] ( #select-fields )
7+ - [ Recursive Descent] ( #recursive-descent )
8+ - [ Slice] ( #slice )
9+ - [ Filter Expression] ( #filter-expression )
10+ - [ Sorter Expression] ( #sorter-expression )
11+ - [ Field-Extractor Expression] ( #field-extractor-expression )
12+ - [ Appendix: Example JSON data:] ( #appendix-example-json-data )
13+ - [ Todo List] ( #todo-list )
1214
1315# jsonpath-python
1416
@@ -24,127 +26,219 @@ A more powerful JSONPath implementation in modern python.
2426- [ ] Support parent operator.
2527- [ ] Support user-defined function.
2628
27- ## Examples
29+ ## JSONPath Syntax
30+
31+ The JSONPath syntax in this project borrows from [ JSONPath - XPath for JSON] ( http://goessner.net/articles/JSONPath/ ) and is ** modified** and ** extended** on it.
32+
33+ ### Operators
2834
29- JSON format data:
35+ | Operator | Description |
36+ | ---------------- | ---------------------------------------------------------------------------- |
37+ | ` $ ` | the root object/element |
38+ | ` @ ` | the current object/element |
39+ | ` . ` or ` [] ` | child operator |
40+ | ` .. ` | recursive descent |
41+ | ` * ` | wildcard |
42+ | ` '' ` | (Experimental) wrap field with special character: dots(` . ` ) and space (` ` ). |
43+ | ` start:end:step ` | array slice operator (It's same as the slice in python) |
44+ | ` ?() ` | applies a filter expression |
45+ | ` /() ` | applies a sorter expression |
46+ | ` () ` | applies a field-extractor expression |
47+
48+ ### Examples
49+
50+ Before running the following example, please import this module and the example data:
3051
3152``` python
32- data = {
33- " store" : {
34- " book" : [
35- {
36- " category" : " reference" ,
37- " author" : " Nigel Rees" ,
38- " title" : " Sayings of the Century" ,
39- " price" : 8.95
40- },
41- {
42- " category" : " fiction" ,
43- " author" : " Evelyn Waugh" ,
44- " title" : " Sword of Honour" ,
45- " price" : 12.99
46- },
47- {
48- " category" : " fiction" ,
49- " author" : " Herman Melville" ,
50- " title" : " Moby Dick" ,
51- " isbn" : " 0-553-21311-3" ,
52- " price" : 8.99
53- },
54- {
55- " category" : " fiction" ,
56- " author" : " J. R. R. Tolkien" ,
57- " title" : " The Lord of the Rings" ,
58- " isbn" : " 0-395-19395-8" ,
59- " price" : 22.99
60- }
61- ],
62- " bicycle" : {
63- " color" : " red" ,
64- " price" : 19.95
65- }
66- }
67- }
53+ >> > from jsonpath import JSONPath
54+
55+ # For the data used in the following example, please refer to the Appendix part.
6856```
6957
70- ### Filter
58+ #### Select Fields
59+
60+ Select a field:
7161
7262``` python
73- >> > JSONPath(' $.store.book[?(@.price>8.95 and @.price<=20 and @.title!="Sword of Honour")]' ).parse(data)
63+ >> > JSONPath(" $.book" ).parse(data)
64+ [[{' category' : ' reference' , ' author' : ' Nigel Rees' , ' title' : ' Sayings of the Century' , ' price' : 8.95 , ' brand' : {' version' : ' v1.0.0' }}, {' category' : ' fiction' , ' author' : ' Evelyn Waugh' , ' title' : ' Sword of Honour' , ' price' : 12.99 , ' brand' : {' version' : ' v0.0.1' }}, {' category' : ' fiction' , ' author' : ' Herman Melville' , ' title' : ' Moby Dick' , ' isbn' : ' 0-553-21311-3' , ' price' : 8.99 , ' brand' : {' version' : ' v1.0.2' }}, {' category' : ' fiction' , ' author' : ' J. R. R. Tolkien' , ' title' : ' The Lord of the Rings' , ' isbn' : ' 0-395-19395-8' , ' price' : 22.99 , ' brand' : {' version' : ' v1.0.3' }}]]
65+ >> > JSONPath(" $[book]" ).parse(data)
66+ [[{' category' : ' reference' , ' author' : ' Nigel Rees' , ' title' : ' Sayings of the Century' , ' price' : 8.95 , ' brand' : {' version' : ' v1.0.0' }}, {' category' : ' fiction' , ' author' : ' Evelyn Waugh' , ' title' : ' Sword of Honour' , ' price' : 12.99 , ' brand' : {' version' : ' v0.0.1' }}, {' category' : ' fiction' , ' author' : ' Herman Melville' , ' title' : ' Moby Dick' , ' isbn' : ' 0-553-21311-3' , ' price' : 8.99 , ' brand' : {' version' : ' v1.0.2' }}, {' category' : ' fiction' , ' author' : ' J. R. R. Tolkien' , ' title' : ' The Lord of the Rings' , ' isbn' : ' 0-395-19395-8' , ' price' : 22.99 , ' brand' : {' version' : ' v1.0.3' }}]]
7467```
7568
76- ``` json
77- [
78- {
79- "category" : " fiction" ,
80- "author" : " Herman Melville" ,
81- "title" : " Moby Dick" ,
82- "isbn" : " 0-553-21311-3" ,
83- "price" : 8.99
84- }
85- ]
69+ (** Experimental** ) Select a field with special character: dots(` . ` ) and space (` ` ).
70+
71+ ``` python
72+ >> > JSONPath(" $.'a.b c'" ).parse(data)
73+ [' a.b c' ]
74+ >> > JSONPath(" $['a.b c']" ).parse(data)
75+ [' a.b c' ]
8676```
8777
88- ### Sorter
78+ Select multiple fields:
8979
9080``` python
91- >> > JSONPath(" $.store.book[/(~category,price)]" ).parse(data)
81+ >> > JSONPath(" $[bicycle,scores]" ).parse(data)
82+ [{' color' : ' red' , ' price' : 19.95 }, {' math' : {' score' : 100 , ' avg' : 60 }, ' english' : {' score' : 95 , ' avg' : 80 }, ' physic' : {' score' : 90 , ' avg' : 70 }, ' chemistry' : {' score' : 85 , ' avg' : 80 }, ' chinese' : {' score' : 60 , ' avg' : 75 }}]
9283```
9384
94- ``` json
95- [
96- {
97- "category" : " reference" ,
98- "author" : " Nigel Rees" ,
99- "title" : " Sayings of the Century" ,
100- "price" : 8.95
101- },
102- {
103- "category" : " fiction" ,
104- "author" : " Herman Melville" ,
105- "title" : " Moby Dick" ,
106- "isbn" : " 0-553-21311-3" ,
107- "price" : 8.99
108- },
109- {
110- "category" : " fiction" ,
111- "author" : " Evelyn Waugh" ,
112- "title" : " Sword of Honour" ,
113- "price" : 12.99
114- },
115- {
116- "category" : " fiction" ,
117- "author" : " J. R. R. Tolkien" ,
118- "title" : " The Lord of the Rings" ,
119- "isbn" : " 0-395-19395-8" ,
120- "price" : 22.99
121- }
122- ]
85+ Select all fields using wildcard ` * ` :
86+
87+ ``` python
88+ >> > JSONPath(" $.*" ).parse(data)
89+ [' a.b c' , [{' category' : ' reference' , ' author' : ' Nigel Rees' , ' title' : ' Sayings of the Century' , ' price' : 8.95 , ' brand' : {' version' : ' v1.0.0' }}, {' category' : ' fiction' , ' author' : ' Evelyn Waugh' , ' title' : ' Sword of Honour' , ' price' : 12.99 , ' brand' : {' version' : ' v0.0.1' }}, {' category' : ' fiction' , ' author' : ' Herman Melville' , ' title' : ' Moby Dick' , ' isbn' : ' 0-553-21311-3' , ' price' : 8.99 , ' brand' : {' version' : ' v1.0.2' }}, {' category' : ' fiction' , ' author' : ' J. R. R. Tolkien' , ' title' : ' The Lord of the Rings' , ' isbn' : ' 0-395-19395-8' , ' price' : 22.99 , ' brand' : {' version' : ' v1.0.3' }}], {' color' : ' red' , ' price' : 19.95 }, {' math' : {' score' : 100 , ' avg' : 60 }, ' english' : {' score' : 95 , ' avg' : 80 }, ' physic' : {' score' : 90 , ' avg' : 70 }, ' chemistry' : {' score' : 85 , ' avg' : 80 }, ' chinese' : {' score' : 60 , ' avg' : 75 }}]
12390```
12491
125- ### Field-Extractor
92+ #### Recursive Descent
12693
12794``` python
128- >> > JSONPath(" $.store.book[*](title,price)" ,result_type = " FIELD" ).parse(data)
95+ >> > JSONPath(" $..price" ).parse(data)
96+ [8.95 , 12.99 , 8.99 , 22.99 , 19.95 ]
12997```
13098
131- ``` json
132- [
133- {
134- "title" : " Sayings of the Century" ,
135- "price" : 8.95
136- },
137- {
138- "title" : " Sword of Honour" ,
139- "price" : 12.99
140- },
141- {
142- "title" : " Moby Dick" ,
143- "price" : 8.99
144- },
145- {
146- "title" : " The Lord of the Rings" ,
147- "price" : 22.99
148- }
149- ]
99+ #### Slice
100+
101+ Support python-like slice.
102+
103+ ``` python
104+ >> > JSONPath(" $.book[1:3]" ).parse(data)
105+ [{' category' : ' fiction' , ' author' : ' Evelyn Waugh' , ' title' : ' Sword of Honour' , ' price' : 12.99 , ' brand' : {' version' : ' v0.0.1' }}, {' category' : ' fiction' , ' author' : ' Herman Melville' , ' title' : ' Moby Dick' , ' isbn' : ' 0-553-21311-3' , ' price' : 8.99 , ' brand' : {' version' : ' v1.0.2' }}]
106+ >> > JSONPath(" $.book[1:-1]" ).parse(data)
107+ [{' category' : ' fiction' , ' author' : ' Evelyn Waugh' , ' title' : ' Sword of Honour' , ' price' : 12.99 , ' brand' : {' version' : ' v0.0.1' }}, {' category' : ' fiction' , ' author' : ' Herman Melville' , ' title' : ' Moby Dick' , ' isbn' : ' 0-553-21311-3' , ' price' : 8.99 , ' brand' : {' version' : ' v1.0.2' }}]
108+ >> > JSONPath(" $.book[0:-1:2]" ).parse(data)
109+ [{' category' : ' reference' , ' author' : ' Nigel Rees' , ' title' : ' Sayings of the Century' , ' price' : 8.95 , ' brand' : {' version' : ' v1.0.0' }}, {' category' : ' fiction' , ' author' : ' Herman Melville' , ' title' : ' Moby Dick' , ' isbn' : ' 0-553-21311-3' , ' price' : 8.99 , ' brand' : {' version' : ' v1.0.2' }}]
110+ >> > JSONPath(" $.book[-1:1]" ).parse(data)
111+ []
112+ >> > JSONPath(" $.book[-1:-11:3]" ).parse(data)
113+ []
114+ >> > JSONPath(" $.book[:]" ).parse(data)
115+ [{' category' : ' reference' , ' author' : ' Nigel Rees' , ' title' : ' Sayings of the Century' , ' price' : 8.95 , ' brand' : {' version' : ' v1.0.0' }}, {' category' : ' fiction' , ' author' : ' Evelyn Waugh' , ' title' : ' Sword of Honour' , ' price' : 12.99 , ' brand' : {' version' : ' v0.0.1' }}, {' category' : ' fiction' , ' author' : ' Herman Melville' , ' title' : ' Moby Dick' , ' isbn' : ' 0-553-21311-3' , ' price' : 8.99 , ' brand' : {' version' : ' v1.0.2' }}, {' category' : ' fiction' , ' author' : ' J. R. R. Tolkien' , ' title' : ' The Lord of the Rings' , ' isbn' : ' 0-395-19395-8' , ' price' : 22.99 , ' brand' : {' version' : ' v1.0.3' }}]
116+ >> > JSONPath(" $.book[::-1]" ).parse(data)
117+ [{' category' : ' fiction' , ' author' : ' J. R. R. Tolkien' , ' title' : ' The Lord of the Rings' , ' isbn' : ' 0-395-19395-8' , ' price' : 22.99 , ' brand' : {' version' : ' v1.0.3' }}, {' category' : ' fiction' , ' author' : ' Herman Melville' , ' title' : ' Moby Dick' , ' isbn' : ' 0-553-21311-3' , ' price' : 8.99 , ' brand' : {' version' : ' v1.0.2' }}, {' category' : ' fiction' , ' author' : ' Evelyn Waugh' , ' title' : ' Sword of Honour' , ' price' : 12.99 , ' brand' : {' version' : ' v0.0.1' }}, {' category' : ' reference' , ' author' : ' Nigel Rees' , ' title' : ' Sayings of the Century' , ' price' : 8.95 , ' brand' : {' version' : ' v1.0.0' }}]
118+
150119```
120+
121+ #### Filter Expression
122+
123+ Support all python comparison operators (` == ` , ` != ` , ` < ` , ` > ` , ` >= ` , ` <= ` ), python membership operators (` in ` , ` not in ` ), python logical operators (` and ` , ` or ` , ` not ` ).
124+
125+ ``` python
126+ >> > JSONPath(" $.book[?(@.price>8 and @.price<9)].price" ).parse(data)
127+ [8.95 , 8.99 ]
128+ >> > JSONPath(' $.book[?(@.category=="reference")].category' ).parse(data)
129+ [' reference' ]
130+ >> > JSONPath(' $.book[?(@.category!="reference" and @.price<9)].title' ).parse(data)
131+ [' Moby Dick' ]
132+ >> > JSONPath(' $.book[?(@.author=="Herman Melville" or @.author=="Evelyn Waugh")].author' ).parse(data)
133+ [' Evelyn Waugh' , ' Herman Melville' ]
134+ ```
135+
136+ ` Note ` : You must use double quote(` "" ` ) instead of single quote(` '' ` ) to wrap the compared string, because single quote(` '' ` ) has another usage in this JSONPath syntax .
137+
138+ #### Sorter Expression
139+
140+ Support sorting by multiple fields (using operator ` , ` ) and reverse sort (using operator ` ~ ` ).
141+
142+ ``` python
143+ >> > JSONPath(" $.book[/(price)].price" ).parse(data)
144+ [8.95 , 8.99 , 12.99 , 22.99 ]
145+ >> > JSONPath(" $.book[/(~price)].price" ).parse(data)
146+ [22.99 , 12.99 , 8.99 , 8.95 ]
147+ >> > JSONPath(" $.book[/(category,price)].price" ).parse(data)
148+ [8.99 , 12.99 , 22.99 , 8.95 ]
149+ >> > JSONPath(" $.book[/(brand.version)].brand.version" ).parse(data)
150+ [' v0.0.1' , ' v1.0.0' , ' v1.0.2' , ' v1.0.3' ]
151+ >> > JSONPath(" $.scores[/(score)].score" ).parse(data)
152+ [60 , 85 , 90 , 95 , 100 ]
153+ ```
154+
155+ #### Field-Extractor Expression
156+
157+ Using ` (field1,field2,…,filedn) ` after a dict object to extract its fields.
158+
159+ ``` python
160+ >> > JSONPath(" $.scores[/(score)].(score)" ).parse(data)
161+ [{' score' : 60 }, {' score' : 85 }, {' score' : 90 }, {' score' : 95 }, {' score' : 100 }]
162+ >> > JSONPath(" $.book[/(category,price)].(title,price)" ).parse(data)
163+ [{' title' : ' Moby Dick' , ' price' : 8.99 }, {' title' : ' Sword of Honour' , ' price' : 12.99 }, {' title' : ' The Lord of the Rings' , ' price' : 22.99 }, {' title' : ' Sayings of the Century' , ' price' : 8.95 }]
164+ ```
165+
166+ ### Appendix: Example JSON data:
167+
168+ ``` python
169+ data = {
170+ " a.b c" : " a.b c" ,
171+ " book" : [
172+ {
173+ " category" : " reference" ,
174+ " author" : " Nigel Rees" ,
175+ " title" : " Sayings of the Century" ,
176+ " price" : 8.95 ,
177+ " brand" : {
178+ " version" : " v1.0.0"
179+ }
180+ },
181+ {
182+ " category" : " fiction" ,
183+ " author" : " Evelyn Waugh" ,
184+ " title" : " Sword of Honour" ,
185+ " price" : 12.99 ,
186+ " brand" : {
187+ " version" : " v0.0.1"
188+ }
189+ },
190+ {
191+ " category" : " fiction" ,
192+ " author" : " Herman Melville" ,
193+ " title" : " Moby Dick" ,
194+ " isbn" : " 0-553-21311-3" ,
195+ " price" : 8.99 ,
196+ " brand" : {
197+ " version" : " v1.0.2"
198+ }
199+ },
200+ {
201+ " category" : " fiction" ,
202+ " author" : " J. R. R. Tolkien" ,
203+ " title" : " The Lord of the Rings" ,
204+ " isbn" : " 0-395-19395-8" ,
205+ " price" : 22.99 ,
206+ " brand" : {
207+ " version" : " v1.0.3"
208+ }
209+ }
210+ ],
211+ " bicycle" : {
212+ " color" : " red" ,
213+ " price" : 19.95
214+ },
215+ " scores" : {
216+ " math" : {
217+ " score" : 100 ,
218+ " avg" : 60
219+ },
220+ " english" : {
221+ " score" : 95 ,
222+ " avg" : 80
223+ },
224+ " physic" : {
225+ " score" : 90 ,
226+ " avg" : 70
227+ },
228+ " chemistry" : {
229+ " score" : 85 ,
230+ " avg" : 80
231+ },
232+ " chinese" : {
233+ " score" : 60 ,
234+ " avg" : 75
235+ }
236+ }
237+ }
238+ ```
239+
240+ ## Todo List
241+
242+ - Syntax and character set (refer to k8s)
243+
244+ > The name segment is required and must be 63 characters or less, beginning and ending with an alphanumeric character (` [a-z0-9A-Z] ` ) with dashes (` - ` ), underscores (` _ ` ), dots (` . ` ), and alphanumerics between.
0 commit comments