@@ -4,8 +4,8 @@ This is an implementation of http://goessner.net/articles/JsonPath/.
44
55## What is JsonPath?
66
7- JsonPath is a way of addressing elements within a JSON object. Similar to xpath of yore, JsonPath lets you
8- traverse a json object and manipulate or access it.
7+ JsonPath is a way of addressing elements within a JSON object. Similar to xpath
8+ of yore, JsonPath lets you traverse a json object and manipulate or access it.
99
1010## Usage
1111
@@ -15,8 +15,8 @@ There is stand-alone usage through the binary `jsonpath`
1515
1616 jsonpath [expression] (file|string)
1717
18- If you omit the second argument, it will read stdin, assuming one valid JSON object
19- per line. Expression must be a valid jsonpath expression.
18+ If you omit the second argument, it will read stdin, assuming one valid JSON
19+ object per line. Expression must be a valid jsonpath expression.
2020
2121### Library
2222
@@ -40,8 +40,8 @@ json = <<-HERE_DOC
4040HERE_DOC
4141```
4242
43- Now that we have a JSON object, let's get all the prices present in the object. We create an object for the path
44- in the following way.
43+ Now that we have a JSON object, let's get all the prices present in the object.
44+ We create an object for the path in the following way.
4545
4646``` ruby
4747path = JsonPath .new (' $..price' )
@@ -54,14 +54,15 @@ path.on(json)
5454# => [19.95, 8.95, 12.99, 8.99, 22.99]
5555```
5656
57- Or on some other object ...
57+ Or reuse it later on some other object (thread safe) ...
5858
5959``` ruby
6060path.on(' {"books":[{"title":"A Tale of Two Somethings","price":18.88}]}' )
6161# => [18.88]
6262```
6363
64- You can also just combine this into one mega-call with the convenient ` JsonPath.on ` method.
64+ You can also just combine this into one mega-call with the convenient
65+ ` JsonPath.on ` method.
6566
6667``` ruby
6768JsonPath .on(json, ' $..author' )
@@ -73,59 +74,114 @@ Of course the full JsonPath syntax is supported, such as array slices
7374``` ruby
7475JsonPath .new (' $..book[::2]' ).on(json)
7576# => [
76- # {"price"=> 8.95, "category"=> "reference", "author"=>"Nigel Rees ", "title"=>"Sayings of the Century "},
77- # {"price"=> 8.99, "category"=> "fiction", "author"=>"Herman Melville" , "title"=> "Moby Dick", "isbn"=>"0-553-21311-3"}
77+ # {"price" => 8.95, "category" => "reference", "title" => "Sayings of the Century ", "author" => "Nigel Rees "},
78+ # {"price" => 8.99, "category" => "fiction", "isbn" => "0-553-21311-3" , "title" => "Moby Dick", "author" => "Herman Melville","color" => "blue"},
7879# ]
7980```
8081
81- ...and evals.
82+ ...and evals, including those with conditional operators
8283
8384``` ruby
84- JsonPath .new (' $..price[?(@ < 10)]' ).on(json)
85+ JsonPath .new (" $..price[?(@ < 10)]" ).on(json)
8586# => [8.95, 8.99]
87+
88+ JsonPath .new (" $..book[?(@['price'] == 8.95 || @['price'] == 8.99)].title" ).on(json)
89+ # => ["Sayings of the Century", "Moby Dick"]
90+
91+ JsonPath .new (" $..book[?(@['price'] == 8.95 && @['price'] == 8.99)].title" ).on(json)
92+ # => []
8693```
8794
88- There is a convenience method, ` #first ` that gives you the first element for a JSON object and path.
95+ There is a convenience method, ` #first ` that gives you the first element for a
96+ JSON object and path.
8997
9098``` ruby
91- JsonPath .new (' $..color' ).first(object )
99+ JsonPath .new (' $..color' ).first(json )
92100# => "red"
93101```
94102
95103As well, we can directly create an ` Enumerable ` at any time using ` #[] ` .
96104
97105``` ruby
98- enum = JsonPath .new (' $..color' )[object ]
106+ enum = JsonPath .new (' $..color' )[json ]
99107# => #<JsonPath::Enumerable:...>
100108enum.first
101109# => "red"
102110enum.any?{ |c | c == ' red' }
103111# => true
104112```
105113
106- ### More examples
114+ For more usage examples and variations on paths, please visit the tests. There
115+ are some more complex ones as well.
107116
108- For more usage examples and variations on paths, please visit the tests. There are some more complex ones as well.
117+ ### Querying ruby data structures
109118
110- ### Conditional Operators Are Also Supported
119+ If you have ruby hashes with symbolized keys as input, you
120+ can use ` :use_symbols ` to make JsonPath work fine on them too:
111121
112122``` ruby
113- def test_or_operator
114- assert_equal [@object [' store' ][' book' ][1 ], @object [' store' ][' book' ][3 ]], JsonPath .new (" $..book[?(@['price'] == 13 || @['price'] == 23)]" ).on(@object )
115- end
123+ book = { title: " Sayings of the Century" }
116124
117- def test_and_operator
118- assert_equal [], JsonPath .new (" $..book[?(@['price'] == 13 && @['price'] == 23)]" ).on(@object )
119- end
125+ JsonPath .new (' $.title' ).on(book)
126+ # => []
120127
121- def test_and_operator_with_more_results
122- assert_equal [@object [' store' ][' book' ][1 ]], JsonPath .new (" $..book[?(@['price'] < 23 && @['price'] > 9)]" ).on(@object )
123- end
128+ JsonPath .new (' $.title' , use_symbols: true ).on(book)
129+ # => ["Sayings of the Century"]
130+ ```
131+
132+ JsonPath also recognizes objects responding to ` dig ` (introduced
133+ in ruby 2.3), and therefore works out of the box with Struct,
134+ OpenStruct, and other Hash-like structures:
135+
136+ ``` ruby
137+ book_class = Struct .new (:title )
138+ book = book_class.new (" Sayings of the Century" )
139+
140+ JsonPath .new (' $.title' ).on(book)
141+ # => ["Sayings of the Century"]
142+ ```
143+
144+ JsonPath is able to query pure ruby objects and uses ` __send__ `
145+ on them. The option is enabled by default in JsonPath 1.x, but
146+ we encourage to enable it explicitly:
147+
148+ ``` ruby
149+ book_class = Class .new { attr_accessor :title }
150+ book = book_class.new
151+ book.title = " Sayings of the Century"
152+
153+ JsonPath .new (' $.title' , allow_send: true ).on(book)
154+ # => ["Sayings of the Century"]
155+ ```
156+
157+ ### Other available options
158+
159+ By default, JsonPath does not return null values on unexisting paths.
160+ This can be changed using the ` :default_path_leaf_to_null ` option
161+
162+ ``` ruby
163+ JsonPath .new (' $..book[*].isbn' ).on(json)
164+ # => ["0-553-21311-3", "0-395-19395-8"]
165+
166+ JsonPath .new (' $..book[*].isbn' , default_path_leaf_to_null: true ).on(json)
167+ # => [nil, nil, "0-553-21311-3", "0-395-19395-8"]
168+ ```
169+
170+ When JsonPath returns a Hash, you can ask to symbolize its keys
171+ using the ` :symbolize_keys ` option
172+
173+ ``` ruby
174+ JsonPath .new (' $..book[0]' ).on(json)
175+ # => [{"category" => "reference", ...}]
176+
177+ JsonPath .new (' $..book[0]' , symbolize_keys: true ).on(json)
178+ # => [{category: "reference", ...}]
124179```
125180
126181### Selecting Values
127182
128- It's possible to select results once a query has been defined after the query. For example given this JSON data:
183+ It's possible to select results once a query has been defined after the query. For
184+ example given this JSON data:
129185
130186``` bash
131187{
@@ -168,15 +224,10 @@ It's possible to select results once a query has been defined after the query. F
168224]
169225` ` `
170226
171- # ## Running an individual test
172-
173- ` ` ` ruby
174- ruby -Ilib:../lib test/test_jsonpath.rb --name test_wildcard_on_intermediary_element_v6
175- ` ` `
176-
177227# ## Manipulation
178228
179- If you' d like to do substitution in a json object, you can use `#gsub` or `#gsub!` to modify the object in place.
229+ If you' d like to do substitution in a json object, you can use `#gsub`
230+ or `#gsub!` to modify the object in place.
180231
181232```ruby
182233JsonPath.for(' {" candy" :" lollipop" }' ).gsub(' $..candy' ) {|v| "big turks" }.to_hash
@@ -188,7 +239,9 @@ The result will be
188239{' candy' => ' big turks' }
189240```
190241
191- If you' d like to remove all nil keys, you can use ` # compact` and `#compact!`. To remove all keys under a certain path, use `#delete` or `#delete!`. You can even chain these methods together as follows:
242+ If you' d like to remove all nil keys, you can use ` # compact` and `#compact!`.
243+ To remove all keys under a certain path, use ` # delete` or ` # delete!` . You can
244+ even chain these methods together as follows:
192245
193246` ` ` ruby
194247json = ' {"candy":"lollipop","noncandy":null,"other":"things"}'
@@ -202,4 +255,11 @@ o = JsonPath.for(json).
202255
203256# Contributions
204257
205- Please feel free to submit an Issue or a Pull Request any time you feel like you would like to contribute. Thank you!
258+ Please feel free to submit an Issue or a Pull Request any time you feel like
259+ you would like to contribute. Thank you!
260+
261+ # # Running an individual test
262+
263+ ` ` ` ruby
264+ ruby -Ilib:../lib test/test_jsonpath.rb --name test_wildcard_on_intermediary_element_v6
265+ ` ` `
0 commit comments