jsonpath 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 762aacec760a67a4097f47df701a1cec0f3f524ae016a2b724873c625c25672d
4
- data.tar.gz: a3076196bc9d30f4cad3ee9c0ab3d58f9bedef4b7d17d7934e7e930c351ee1c0
3
+ metadata.gz: 3d49972014868528c0c690ecec0ec7d6e06056f14a803637d494c87ee3100de0
4
+ data.tar.gz: fbbb8f93028b2aac45f6727aba4e874c51db91bb599bc568ec62c94180595a91
5
5
  SHA512:
6
- metadata.gz: 7894391f0693b7ebb3f3d8bca20dcf2eeb54af85e6ca268ff75fe120c64ae5e8ff09fa9a7b82cacbb8a5776d03dfa0f9bcc1f4716eea63988910cbb501d64236
7
- data.tar.gz: c0f5c57d5c527a432a1c02fa728e32f8f8a7009efd0a31778b2766d97eba1e752ec1779e2d725fc233731f64541be72c9e896a511f312f8b5e3a4a1ed3e31a8d
6
+ metadata.gz: 60c7d6e4075b9ece68f6325d2b836f228b780304ac0ddafbfe2154668f07c10d4faee371135b9b9c55f7548a89a7f755d6536b4305e47f486112549c9b2711b1
7
+ data.tar.gz: cf72f327c8a3d12bb4780cf052846e9183218148dcf5e57fcddaeb0c1b86218f9a082d4b3cb7f7e38e390956176da71a954e855ae33436f9ce396a1eb73fd2f7
data/README.md CHANGED
@@ -123,6 +123,51 @@ For more usage examples and variations on paths, please visit the tests. There a
123
123
  end
124
124
  ```
125
125
 
126
+ ### Selecting Values
127
+
128
+ It's possible to select results once a query has been defined after the query. For example given this JSON data:
129
+
130
+ ```bash
131
+ {
132
+ "store": {
133
+ "book": [
134
+ {
135
+ "category": "reference",
136
+ "author": "Nigel Rees",
137
+ "title": "Sayings of the Century",
138
+ "price": 8.95
139
+ },
140
+ {
141
+ "category": "fiction",
142
+ "author": "Evelyn Waugh",
143
+ "title": "Sword of Honour",
144
+ "price": 12.99
145
+ }
146
+ ]
147
+ }
148
+ ```
149
+
150
+ ... and this query:
151
+
152
+ ```ruby
153
+ "$.store.book[*](category,author)"
154
+ ```
155
+
156
+ ... the result can be filtered as such:
157
+
158
+ ```bash
159
+ [
160
+ {
161
+ "category" : "reference",
162
+ "author" : "Nigel Rees"
163
+ },
164
+ {
165
+ "category" : "fiction",
166
+ "author" : "Evelyn Waugh"
167
+ }
168
+ ]
169
+ ```
170
+
126
171
  ### Running an individual test
127
172
 
128
173
  ```ruby
@@ -10,7 +10,7 @@ require 'jsonpath/parser'
10
10
  # JsonPath: initializes the class with a given JsonPath and parses that path
11
11
  # into a token array.
12
12
  class JsonPath
13
- PATH_ALL = '$..*'.freeze
13
+ PATH_ALL = '$..*'
14
14
 
15
15
  attr_accessor :path
16
16
 
@@ -19,21 +19,23 @@ class JsonPath
19
19
  scanner = StringScanner.new(path.strip)
20
20
  @path = []
21
21
  until scanner.eos?
22
- if token = scanner.scan(/\$\B|@\B|\*|\.\./)
22
+ if (token = scanner.scan(/\$\B|@\B|\*|\.\./))
23
23
  @path << token
24
- elsif token = scanner.scan(/[\$@a-zA-Z0-9:{}_-]+/)
24
+ elsif (token = scanner.scan(/[$@a-zA-Z0-9:{}_-]+/))
25
25
  @path << "['#{token}']"
26
- elsif token = scanner.scan(/'(.*?)'/)
26
+ elsif (token = scanner.scan(/'(.*?)'/))
27
27
  @path << "[#{token}]"
28
- elsif token = scanner.scan(/\[/)
28
+ elsif (token = scanner.scan(/\[/))
29
29
  @path << find_matching_brackets(token, scanner)
30
- elsif token = scanner.scan(/\]/)
30
+ elsif (token = scanner.scan(/\]/))
31
31
  raise ArgumentError, 'unmatched closing bracket'
32
+ elsif (token = scanner.scan(/\(.*\)/))
33
+ @path << token
32
34
  elsif scanner.scan(/\./)
33
35
  nil
34
- elsif token = scanner.scan(/[><=] \d+/)
36
+ elsif (token = scanner.scan(/[><=] \d+/))
35
37
  @path.last << token
36
- elsif token = scanner.scan(/./)
38
+ elsif (token = scanner.scan(/./))
37
39
  begin
38
40
  @path.last << token
39
41
  rescue RuntimeError
@@ -46,13 +48,13 @@ class JsonPath
46
48
  def find_matching_brackets(token, scanner)
47
49
  count = 1
48
50
  until count.zero?
49
- if t = scanner.scan(/\[/)
51
+ if (t = scanner.scan(/\[/))
50
52
  token << t
51
53
  count += 1
52
- elsif t = scanner.scan(/\]/)
54
+ elsif (t = scanner.scan(/\]/))
53
55
  token << t
54
56
  count -= 1
55
- elsif t = scanner.scan(/[^\[\]]+/)
57
+ elsif (t = scanner.scan(/[^\[\]]+/))
56
58
  token << t
57
59
  elsif scanner.eos?
58
60
  raise ArgumentError, 'unclosed bracket'
@@ -28,6 +28,10 @@ class JsonPath
28
28
  each(context, key, pos + 1, &blk) if node == @object
29
29
  when /^\[(.*)\]$/
30
30
  handle_wildecard(node, expr, context, key, pos, &blk)
31
+ when /\(.*\)/
32
+ keys = expr.gsub(/[()]/, '').split(',').map(&:strip)
33
+ new_context = filter_context(context, keys)
34
+ yield_value(blk, new_context, key)
31
35
  end
32
36
 
33
37
  if pos > 0 && @path[pos - 1] == '..' || (@path[pos - 1] == '*' && @path[pos] != '..')
@@ -40,6 +44,18 @@ class JsonPath
40
44
 
41
45
  private
42
46
 
47
+ def filter_context(context, keys)
48
+ case context
49
+ when Hash
50
+ # TODO: Change this to `slice(*keys)` when ruby version support is > 2.4
51
+ context.select { |k| keys.include?(k) }
52
+ when Array
53
+ context.each_with_object([]) do |c, memo|
54
+ memo << c.select { |k| keys.include?(k) }
55
+ end
56
+ end
57
+ end
58
+
43
59
  def handle_wildecard(node, expr, _context, _key, pos, &blk)
44
60
  expr[1, expr.size - 2].split(',').each do |sub_path|
45
61
  case sub_path[0]
@@ -65,7 +65,7 @@ class JsonPath
65
65
  elements = []
66
66
  until scanner.eos?
67
67
  if (t = scanner.scan(/\['[a-zA-Z@&*\/$%^?_]+'\]|\.[a-zA-Z0-9_]+[?!]?/))
68
- elements << t.gsub(/[\[\]'\.]|\s+/, '')
68
+ elements << t.gsub(/[\[\]'.]|\s+/, '')
69
69
  elsif (t = scanner.scan(/(\s+)?[<>=!\-+][=~]?(\s+)?/))
70
70
  operator = t
71
71
  elsif (t = scanner.scan(/(\s+)?'?.*'?(\s+)?/))
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class JsonPath
4
- VERSION = '1.0.3'.freeze
4
+ VERSION = '1.0.4'
5
5
  end
@@ -833,6 +833,82 @@ class TestJsonpath < MiniTest::Unit::TestCase
833
833
  assert_equal [], JsonPath.on(json, "$.phoneNumbers[?(@[0].type == 'home')]")
834
834
  end
835
835
 
836
+ def test_selecting_multiple_keys
837
+ json = '
838
+ {
839
+ "store": {
840
+ "book": [
841
+ {
842
+ "category": "reference",
843
+ "author": "Nigel Rees",
844
+ "title": "Sayings of the Century",
845
+ "price": 8.95
846
+ },
847
+ {
848
+ "category": "fiction",
849
+ "author": "Evelyn Waugh",
850
+ "title": "Sword of Honour",
851
+ "price": 12.99
852
+ }
853
+ ]
854
+ }
855
+ }
856
+ '.to_json
857
+
858
+ assert_equal [{ 'category' => 'reference', 'author' => 'Nigel Rees' }, { 'category' => 'fiction', 'author' => 'Evelyn Waugh' }], JsonPath.on(json, '$.store.book[*](category,author)')
859
+ end
860
+
861
+ def test_selecting_multiple_keys_with_filter
862
+ json = '
863
+ {
864
+ "store": {
865
+ "book": [
866
+ {
867
+ "category": "reference",
868
+ "author": "Nigel Rees",
869
+ "title": "Sayings of the Century",
870
+ "price": 8.95
871
+ },
872
+ {
873
+ "category": "fiction",
874
+ "author": "Evelyn Waugh",
875
+ "title": "Sword of Honour",
876
+ "price": 12.99
877
+ }
878
+ ]
879
+ }
880
+ }
881
+ '.to_json
882
+
883
+ assert_equal [{ 'category' => 'reference', 'author' => 'Nigel Rees' }], JsonPath.on(json, "$.store.book[?(@['price'] == 8.95)](category,author)")
884
+ assert_equal [{ 'category' => 'reference', 'author' => 'Nigel Rees' }], JsonPath.on(json, "$.store.book[?(@['price'] == 8.95)]( category, author )")
885
+ end
886
+
887
+ def test_selecting_multiple_keys_with_filter_with_space_in_catergory
888
+ json = '
889
+ {
890
+ "store": {
891
+ "book": [
892
+ {
893
+ "cate gory": "reference",
894
+ "author": "Nigel Rees",
895
+ "title": "Sayings of the Century",
896
+ "price": 8.95
897
+ },
898
+ {
899
+ "cate gory": "fiction",
900
+ "author": "Evelyn Waugh",
901
+ "title": "Sword of Honour",
902
+ "price": 12.99
903
+ }
904
+ ]
905
+ }
906
+ }
907
+ '.to_json
908
+
909
+ assert_equal [{ 'cate gory' => 'reference', 'author' => 'Nigel Rees' }], JsonPath.on(json, "$.store.book[?(@['price'] == 8.95)]( cate gory, author )")
910
+ end
911
+
836
912
  def example_object
837
913
  { 'store' => {
838
914
  'book' => [
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonpath
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua Hull
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-05-26 00:00:00.000000000 Z
12
+ date: 2019-06-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: multi_json
@@ -158,7 +158,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
158
158
  - !ruby/object:Gem::Version
159
159
  version: '0'
160
160
  requirements: []
161
- rubygems_version: 3.0.3
161
+ rubyforge_project: jsonpath
162
+ rubygems_version: 2.7.3
162
163
  signing_key:
163
164
  specification_version: 4
164
165
  summary: Ruby implementation of http://goessner.net/articles/JsonPath/