File: README.md

package info (click to toggle)
ruby-jsonpath 1.0.5-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, sid
  • size: 220 kB
  • sloc: ruby: 1,327; makefile: 4
file content (205 lines) | stat: -rw-r--r-- 5,186 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# JsonPath

This is an implementation of http://goessner.net/articles/JsonPath/.

## What is JsonPath?

JsonPath is a way of addressing elements within a JSON object. Similar to xpath of yore, JsonPath lets you
traverse a json object and manipulate or access it.

## Usage

### Command-line

There is stand-alone usage through the binary `jsonpath`

    jsonpath [expression] (file|string)

    If you omit the second argument, it will read stdin, assuming one valid JSON object
    per line. Expression must be a valid jsonpath expression.

### Library

To use JsonPath as a library simply include and get goin'!

```ruby
require 'jsonpath'

json = <<-HERE_DOC
{"store":
  {"bicycle":
    {"price":19.95, "color":"red"},
    "book":[
      {"price":8.95, "category":"reference", "title":"Sayings of the Century", "author":"Nigel Rees"},
      {"price":12.99, "category":"fiction", "title":"Sword of Honour", "author":"Evelyn Waugh"},
      {"price":8.99, "category":"fiction", "isbn":"0-553-21311-3", "title":"Moby Dick", "author":"Herman Melville","color":"blue"},
      {"price":22.99, "category":"fiction", "isbn":"0-395-19395-8", "title":"The Lord of the Rings", "author":"Tolkien"}
    ]
  }
}
HERE_DOC
```

Now that we have a JSON object, let's get all the prices present in the object. We create an object for the path
in the following way.

```ruby
path = JsonPath.new('$..price')
```

Now that we have a path, let's apply it to the object above.

```ruby
path.on(json)
# => [19.95, 8.95, 12.99, 8.99, 22.99]
```

Or on some other object ...

```ruby
path.on('{"books":[{"title":"A Tale of Two Somethings","price":18.88}]}')
# => [18.88]
```

You can also just combine this into one mega-call with the convenient `JsonPath.on` method.

```ruby
JsonPath.on(json, '$..author')
# => ["Nigel Rees", "Evelyn Waugh", "Herman Melville", "Tolkien"]
```

Of course the full JsonPath syntax is supported, such as array slices

```ruby
JsonPath.new('$..book[::2]').on(json)
# => [
#      {"price"=>8.95, "category"=>"reference", "author"=>"Nigel Rees", "title"=>"Sayings of the Century"},
#      {"price"=>8.99, "category"=>"fiction", "author"=>"Herman Melville", "title"=>"Moby Dick", "isbn"=>"0-553-21311-3"}
#    ]
```

...and evals.

```ruby
JsonPath.new('$..price[?(@ < 10)]').on(json)
# => [8.95, 8.99]
```

There is a convenience method, `#first` that gives you the first element for a JSON object and path.

```ruby
JsonPath.new('$..color').first(object)
# => "red"
```

As well, we can directly create an `Enumerable` at any time using `#[]`. 

```ruby
enum = JsonPath.new('$..color')[object]
# => #<JsonPath::Enumerable:...>
enum.first
# => "red"
enum.any?{ |c| c == 'red' }
# => true
```

### More examples

For more usage examples and variations on paths, please visit the tests. There are some more complex ones as well.

### Conditional Operators Are Also Supported

```ruby
  def test_or_operator
    assert_equal [@object['store']['book'][1], @object['store']['book'][3]], JsonPath.new("$..book[?(@['price'] == 13 || @['price'] == 23)]").on(@object)
  end

  def test_and_operator
    assert_equal [], JsonPath.new("$..book[?(@['price'] == 13 && @['price'] == 23)]").on(@object)
  end

  def test_and_operator_with_more_results
    assert_equal [@object['store']['book'][1]], JsonPath.new("$..book[?(@['price'] < 23 && @['price'] > 9)]").on(@object)
  end
```

### Selecting Values

It's possible to select results once a query has been defined after the query. For example given this JSON data:

```bash
{
    "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
            }
        ]
}
```

... and this query:

```ruby
"$.store.book[*](category,author)"
```

... the result can be filtered as such:

```bash
[
   {
      "category" : "reference",
      "author" : "Nigel Rees"
   },
   {
      "category" : "fiction",
      "author" : "Evelyn Waugh"
   }
]
```

### Running an individual test

```ruby
ruby -Ilib:../lib test/test_jsonpath.rb --name test_wildcard_on_intermediary_element_v6
```

### Manipulation

If you'd like to do substitution in a json object, you can use `#gsub` or `#gsub!` to modify the object in place.

```ruby
JsonPath.for('{"candy":"lollipop"}').gsub('$..candy') {|v| "big turks" }.to_hash
```

The result will be

```ruby
{'candy' => 'big turks'}
```

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:

```ruby
json = '{"candy":"lollipop","noncandy":null,"other":"things"}'
o = JsonPath.for(json).
  gsub('$..candy') {|v| "big turks" }.
  compact.
  delete('$..other').
  to_hash
# => {"candy" => "big turks"}
```

# Contributions

Please feel free to submit an Issue or a Pull Request any time you feel like you would like to contribute. Thank you!