json_scanner 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +69 -3
- data/ext/json_scanner/json_scanner.c +449 -94
- data/ext/json_scanner/json_scanner.h +1 -0
- data/lib/json_scanner/version.rb +1 -1
- data/spec/extensiontesttask.rb +128 -0
- data/spec/json_scanner_spec.c +0 -0
- data/spec/json_scanner_spec.rb +303 -16
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9c1ddff519827bc802cdcacb5b048402706544b0882c8ac91cd1aa414c4b57e0
|
4
|
+
data.tar.gz: d1c4f41dbd71ed08a488c2f9647194fd2692c91d522fee35d28d7060bf80321c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 57bf59cc9495f46675bb98d2fc7545bdc3b8392631c443ad2b89595b22be054c8f8bb268a798c5f104d1e38b73d577662f96637fd9311260c9b0a45b55044265
|
7
|
+
data.tar.gz: '055432559a23dbf34e679aac7be4967ea163684fda718b433e978c34feb73f298f1346b00629fada8279a9e49e1267b990f73d2d57c8403330faf42ce4086bb8'
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
# JsonScanner
|
4
4
|
|
5
|
-
Extract values from JSON without full parsing. This gem uses yajl
|
5
|
+
Extract values from JSON without full parsing. This gem uses the `yajl` library to scan a JSON string and allows you to parse pieces of it.
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
@@ -16,6 +16,8 @@ If bundler is not being used to manage dependencies, install the gem by executin
|
|
16
16
|
|
17
17
|
## Usage
|
18
18
|
|
19
|
+
Basic usage
|
20
|
+
|
19
21
|
```ruby
|
20
22
|
require "json"
|
21
23
|
require "json_scanner"
|
@@ -32,13 +34,77 @@ emoji_json = '{"grin": "😁", "heart": "😍", "rofl": "🤣"}'
|
|
32
34
|
begin_pos, end_pos, = JsonScanner.scan(emoji_json, [["heart"]], false).first.first
|
33
35
|
emoji_json.byteslice(begin_pos...end_pos)
|
34
36
|
# => "\"😍\""
|
35
|
-
# Note: most likely don't need `quirks_mode` option
|
36
|
-
#
|
37
|
+
# Note: You most likely don't need the `quirks_mode` option unless you are using an older version
|
38
|
+
# of Ruby with the stdlib - or just also old - version of the json gem. In newer versions, `quirks_mode` is enabled by default.
|
37
39
|
JSON.parse(emoji_json.byteslice(begin_pos...end_pos), quirks_mode: true)
|
38
40
|
# => "😍"
|
39
41
|
# You can also do this
|
40
42
|
# emoji_json.force_encoding(Encoding::BINARY)[begin_pos...end_pos].force_encoding(Encoding::UTF_8)
|
41
43
|
# => "\"😍\""
|
44
|
+
|
45
|
+
# Ranges are supported as matchers for indexes with the following restrictions:
|
46
|
+
# - the start of a range must be positive
|
47
|
+
# - the end of a range must be positive or -1
|
48
|
+
# - a range with -1 end must be closed, e.g. (0..-1) works, but (0...-1) is forbidden
|
49
|
+
JsonScanner.scan('[0, 42, 0]', [[(1..-1)]])
|
50
|
+
# => [[[4, 6, :number], [8, 9, :number]]]
|
51
|
+
JsonScanner.scan('[0, 42, 0]', [[JsonScanner::ANY_INDEX]])
|
52
|
+
# => [[[1, 2, :number], [4, 6, :number], [8, 9, :number]]]
|
53
|
+
|
54
|
+
# Special matcher JsonScanner::ANY_KEY is supported for object keys
|
55
|
+
JsonScanner.scan('{"a": 1, "b": 2}', [[JsonScanner::ANY_KEY]], with_path: true)
|
56
|
+
# => [[[["a"], [6, 7, :number]], [["b"], [14, 15, :number]]]]
|
57
|
+
```
|
58
|
+
|
59
|
+
It supports multiple options
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
JsonScanner.scan('[0, 42, 0]', [[(1..-1)]], with_path: true)
|
63
|
+
# => [[[[1], [4, 6, :number]], [[2], [8, 9, :number]]]]
|
64
|
+
JsonScanner.scan('[0, 42,', [[(1..-1)]], verbose_error: true)
|
65
|
+
# JsonScanner::ParseError (parse error: premature EOF)
|
66
|
+
# [0, 42,
|
67
|
+
# (right here) ------^
|
68
|
+
JsonScanner.scan('[0, /* answer */ 42, 0]', [[(1..-1)]], allow_comments: true)
|
69
|
+
# => [[[17, 19, :number], [21, 22, :number]]]
|
70
|
+
JsonScanner.scan("\"\x81\x83\"", [[]], dont_validate_strings: true)
|
71
|
+
# => [[[0, 4, :string]]]
|
72
|
+
JsonScanner.scan("{\"\x81\x83\": 42}", [[JsonScanner::ANY_KEY]], dont_validate_strings: true, with_path: true)
|
73
|
+
# => [[[["\x81\x83"], [7, 9, :number]]]]
|
74
|
+
JsonScanner.scan('[0, 42, 0]garbage', [[(1..-1)]], allow_trailing_garbage: true)
|
75
|
+
# => [[[4, 6, :number], [8, 9, :number]]]
|
76
|
+
JsonScanner.scan('[0, 42, 0] [0, 34]', [[(1..-1)]], allow_multiple_values: true)
|
77
|
+
# => [[[4, 6, :number], [8, 9, :number], [16, 18, :number]]]
|
78
|
+
JsonScanner.scan('[0, 42, 0', [[(1..-1)]], allow_partial_values: true)
|
79
|
+
# => [[[4, 6, :number], [8, 9, :number]]]
|
80
|
+
JsonScanner.scan('{"a": 1}', [[JsonScanner::ANY_KEY]], with_path: true, symbolize_path_keys: true)
|
81
|
+
# => [[[[:a], [6, 7, :number]]]]
|
82
|
+
```
|
83
|
+
|
84
|
+
Note that the standard `JSON` library supports comments, so you may want to enable it in the `JsonScanner` as well
|
85
|
+
```ruby
|
86
|
+
json_str = '{"answer": {"value": 42 /* the Ultimate Question of Life, the Universe, and Everything */ }}'
|
87
|
+
JsonScanner.scan(json_str, [["answer"]], allow_comments: true).first.map do |begin_pos, end_pos, _type|
|
88
|
+
JSON.parse(json_str.byteslice(begin_pos...end_pos), quirks_mode: true)
|
89
|
+
end
|
90
|
+
# => [{"value"=>42}]
|
91
|
+
```
|
92
|
+
|
93
|
+
You can also create a config and reuse it
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
require "json_scanner"
|
97
|
+
|
98
|
+
config = JsonScanner::Config.new([[], ["key"], [(0..-1)]])
|
99
|
+
# => #<JsonScanner::Config [[], ['key'], [(0..9223372036854775807)]]>
|
100
|
+
JsonScanner.scan('{"key": "42"}', config)
|
101
|
+
# => [[[0, 13, :object]], [[8, 12, :string]], []]
|
102
|
+
JsonScanner.scan('{"key": "42"}', config, with_path: true)
|
103
|
+
# => [[[[], [0, 13, :object]]], [[["key"], [8, 12, :string]]], []]
|
104
|
+
JsonScanner.scan('[0, 42]', config)
|
105
|
+
# => [[[0, 7, :array]], [], [[1, 2, :number], [4, 6, :number]]]
|
106
|
+
JsonScanner.scan('[0, 42]', config, with_path: true)
|
107
|
+
# => [[[[], [0, 7, :array]]], [], [[[0], [1, 2, :number]], [[1], [4, 6, :number]]]]
|
42
108
|
```
|
43
109
|
|
44
110
|
## Development
|