json-streamer 2.0.1 → 2.1.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 +5 -5
- data/.travis.yml +4 -0
- data/README.md +95 -24
- data/json-streamer.gemspec +1 -0
- data/lib/json/streamer.rb +2 -2
- data/lib/json/streamer/json_streamer.rb +30 -7
- data/lib/json/streamer/version.rb +1 -1
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8a3dd5e19a0ad214f6121458dd0de84db79a45ba2f321a83eadfbb26de2f575c
|
4
|
+
data.tar.gz: 55099a1cddf21b0392eae5306b74d9e7e7fd2665d12fd5c995a972786afc2d71
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 87c6bbe06080168b7711c6620aa8522f6d86976db1dc826e889b1ca02b29ca467c89e054aba36063b392fb8a9052945fc60c08009853cd89ea6ec1481d23ca9a
|
7
|
+
data.tar.gz: 3335826bd0f377b72db28fbbdeb882067f84203f03fc68eb6e957bda0a19c82790ffe743117442cee49bcff4fde285675e054d4b3ff05ecb103c864c52035124
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,18 +1,27 @@
|
|
1
1
|
# Json::Streamer
|
2
2
|
|
3
|
-
#### Ruby
|
3
|
+
#### Ruby gem for getting data from JSON streams based on various criteria (key, nesting level, etc).
|
4
|
+
|
5
|
+
Status and support
|
6
|
+
|
7
|
+
- ✔ stable
|
8
|
+
- ✔ supported
|
9
|
+
- ✖ no ongoing development
|
10
|
+
|
11
|
+
<!--- Version informartion -->
|
12
|
+
*You are viewing the README of version [v2.1.0](https://github.com/thisismydesign/json-streamer/releases/tag/v2.1.0). You can find other releases [here](https://github.com/thisismydesign/json-streamer/releases).*
|
13
|
+
<!--- Version informartion end -->
|
4
14
|
|
5
15
|
| Branch | Status |
|
6
16
|
| ------ | ------ |
|
7
17
|
| Release | [](https://travis-ci.org/thisismydesign/json-streamer) [](https://coveralls.io/github/thisismydesign/json-streamer?branch=release) [](https://badge.fury.io/rb/json-streamer) [](https://rubygems.org/gems/json-streamer) |
|
8
18
|
| Development | [](https://travis-ci.org/thisismydesign/json-streamer) [](https://coveralls.io/github/thisismydesign/json-streamer?branch=master) |
|
9
19
|
|
10
|
-
|
20
|
+
#### If you've tried JSON streaming with other Ruby libraries before (e.g. [JSON::Stream](https://github.com/dgraham/json-stream), [Yajl::FFI](https://github.com/dgraham/yajl-ffi))
|
11
21
|
|
12
22
|
This gem will basically spare you the need to define your own callbacks (i.e. implement an actual JSON parser using `start_object`, `end_object`, `key`, `value`, etc.).
|
13
23
|
|
14
|
-
|
15
|
-
*If you're new to this:*
|
24
|
+
#### If you're new to this
|
16
25
|
|
17
26
|
Streaming is useful for
|
18
27
|
- big files that do not fit in the memory (or you'd rather avoid the risk)
|
@@ -21,12 +30,16 @@ Streaming is useful for
|
|
21
30
|
|
22
31
|
This gem is aimed at making streaming as easy and convenient as possible.
|
23
32
|
|
24
|
-
|
33
|
+
#### Performance
|
34
|
+
|
35
|
+
Highly depends on the event generator. Out of the box the gem uses [JSON::Stream](https://github.com/dgraham/json-stream). It was chosen because it's a pure Ruby parser with no runtime dependencies. You can use any custom event generator, such as [Yajl::FFI](https://github.com/dgraham/yajl-ffi) which is dependent on the native YAJL library and is [~10 times faster](https://github.com/dgraham/yajl-ffi#performance). See the [Custom event generators](#custom-event-generators) chapter.
|
25
36
|
|
26
|
-
The gem uses JSON::Stream's events in the background. It was chosen because it's a pure Ruby parser.
|
27
|
-
A similar implementation can be done using the ~10 times faster Yajl::FFI gem that is dependent on the native YAJL library.
|
28
37
|
I did not measure the performance of my implementation on top of these libraries.
|
29
38
|
|
39
|
+
#### Dependencies
|
40
|
+
|
41
|
+
The gem's single runtime dependency is [JSON::Stream](https://github.com/dgraham/json-stream). It is only loaded if the default event generator is used.
|
42
|
+
|
30
43
|
## Installation
|
31
44
|
|
32
45
|
Add this line to your application's Gemfile:
|
@@ -45,18 +58,14 @@ Or install it yourself as:
|
|
45
58
|
|
46
59
|
## Usage
|
47
60
|
|
48
|
-
Check the unit tests for more examples ([spec/streamer_spec.rb](spec/json/streamer/json_streamer_spec.rb)).
|
49
|
-
|
50
|
-
One `streamer` object handles one set of conditions. For multiple conditions create multiple streamers. For more details see [this discussion](https://github.com/thisismydesign/json-streamer/issues/9).
|
51
|
-
|
52
61
|
```ruby
|
53
62
|
require 'json/streamer'
|
54
63
|
```
|
55
64
|
|
56
|
-
### v1.2 (and above) API
|
57
|
-
|
58
65
|
#### Passing IO upfront
|
59
66
|
|
67
|
+
Since [v1.2.0](https://github.com/thisismydesign/json-streamer/releases/tag/v1.2.0)
|
68
|
+
|
60
69
|
```ruby
|
61
70
|
file_stream = File.open('data.json', 'r')
|
62
71
|
chunk_size = 500 # defaults to 1000
|
@@ -181,9 +190,23 @@ def receive_data(data)
|
|
181
190
|
end
|
182
191
|
```
|
183
192
|
|
193
|
+
#### Custom event generators
|
194
|
+
|
195
|
+
Since [v2.1.0](https://github.com/thisismydesign/json-streamer/releases/tag/v2.1.0)
|
196
|
+
|
197
|
+
```ruby
|
198
|
+
require "yajl/ffi"
|
199
|
+
|
200
|
+
Json::Streamer.parser(event_generator: Yajl::FFI::Parser.new)
|
201
|
+
```
|
202
|
+
|
203
|
+
Any parser can be used that provides the right events. The gem is tested with [Yajl::FFI](https://github.com/dgraham/yajl-ffi) and [JSON::Stream](https://github.com/dgraham/json-stream).
|
204
|
+
|
184
205
|
#### Custom yield conditions
|
185
206
|
|
186
|
-
[v2.0.0](https://github.com/thisismydesign/json-streamer/releases/tag/v2.0.0)
|
207
|
+
Since [v2.0.0](https://github.com/thisismydesign/json-streamer/releases/tag/v2.0.0)
|
208
|
+
|
209
|
+
Custom conditions provide ultimate control over what to yield.
|
187
210
|
|
188
211
|
The Conditions API exposes 3 callbacks:
|
189
212
|
- `yield_value`
|
@@ -246,7 +269,61 @@ Output:
|
|
246
269
|
{"key2"=>"value"}
|
247
270
|
```
|
248
271
|
|
249
|
-
|
272
|
+
#### Get an Enumerable when not passing a block
|
273
|
+
|
274
|
+
Since [v2.1.0](https://github.com/thisismydesign/json-streamer/releases/tag/v2.1.0)
|
275
|
+
|
276
|
+
When _not_ passed a block both `get` and `get_with_conditions` return an enumerator of the requested objects. When passed a block they return an empty enumerator. This means that **when _not_ passed a block the requested objects will accumulate in memory**.
|
277
|
+
|
278
|
+
Without block
|
279
|
+
|
280
|
+
```ruby
|
281
|
+
objects = streamer.get(nesting_level:1)
|
282
|
+
p objects
|
283
|
+
```
|
284
|
+
|
285
|
+
Input:
|
286
|
+
```json
|
287
|
+
{
|
288
|
+
"object1": "first_level_value",
|
289
|
+
"object2": {}
|
290
|
+
}
|
291
|
+
```
|
292
|
+
|
293
|
+
Output:
|
294
|
+
```ruby
|
295
|
+
["first_level_value", {}]
|
296
|
+
```
|
297
|
+
|
298
|
+
With block
|
299
|
+
|
300
|
+
```ruby
|
301
|
+
unyielded_objects = streamer.get(nesting_level:1) { |object| do_something(object) }
|
302
|
+
p unyielded_objects
|
303
|
+
```
|
304
|
+
|
305
|
+
Input:
|
306
|
+
```json
|
307
|
+
{
|
308
|
+
"object1": "first_level_value",
|
309
|
+
"object2": {}
|
310
|
+
}
|
311
|
+
```
|
312
|
+
|
313
|
+
Output:
|
314
|
+
```ruby
|
315
|
+
[]
|
316
|
+
```
|
317
|
+
|
318
|
+
#### Other usage information
|
319
|
+
|
320
|
+
Check the unit tests for more examples ([spec/streamer_spec.rb](spec/json/streamer/json_streamer_spec.rb)).
|
321
|
+
|
322
|
+
One `streamer` object handles one set of conditions. For multiple conditions create multiple streamers. For more details see [this discussion](https://github.com/thisismydesign/json-streamer/issues/9).
|
323
|
+
|
324
|
+
#### Deprecated API
|
325
|
+
|
326
|
+
Pre [v1.2.0](https://github.com/thisismydesign/json-streamer/releases/tag/v1.2.0)
|
250
327
|
|
251
328
|
This functionality is deprecated but kept for compatibility reasons.
|
252
329
|
|
@@ -260,13 +337,11 @@ streamer = Json::Streamer::JsonStreamer.new
|
|
260
337
|
streamer.parser << data
|
261
338
|
```
|
262
339
|
|
263
|
-
##
|
264
|
-
|
265
|
-
Any feedback is much appreciated.
|
340
|
+
## Contribution and feedback
|
266
341
|
|
267
|
-
|
342
|
+
This project is built around known use-cases. If have one that isn't covered don't hesitate to open an issue and start a discussion.
|
268
343
|
|
269
|
-
|
344
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/thisismydesign/json-streamer. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
270
345
|
|
271
346
|
## Conventions
|
272
347
|
|
@@ -278,10 +353,6 @@ This gem is developed using the following conventions:
|
|
278
353
|
- [RFC memo about key words used to Indicate Requirement Levels](https://tools.ietf.org/html/rfc2119)
|
279
354
|
- [Bundler improvements](https://github.com/thisismydesign/bundler-improvements)
|
280
355
|
|
281
|
-
## Contributing
|
282
|
-
|
283
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/thisismydesign/json-streamer. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
284
|
-
|
285
356
|
## License
|
286
357
|
|
287
358
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/json-streamer.gemspec
CHANGED
@@ -30,6 +30,7 @@ Gem::Specification.new do |spec|
|
|
30
30
|
spec.add_development_dependency "guard"
|
31
31
|
spec.add_development_dependency "guard-bundler"
|
32
32
|
spec.add_development_dependency "guard-rspec"
|
33
|
+
spec.add_development_dependency "yajl-ffi"
|
33
34
|
|
34
35
|
spec.add_dependency "json-stream"
|
35
36
|
end
|
data/lib/json/streamer.rb
CHANGED
@@ -2,8 +2,8 @@ require_relative "streamer/json_streamer"
|
|
2
2
|
|
3
3
|
module Json
|
4
4
|
module Streamer
|
5
|
-
def self.parser(file_io: nil, chunk_size: 1000)
|
6
|
-
JsonStreamer.new(file_io, chunk_size)
|
5
|
+
def self.parser(file_io: nil, chunk_size: 1000, event_generator: :default)
|
6
|
+
JsonStreamer.new(file_io, chunk_size, event_generator)
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require "json/stream"
|
2
|
-
|
3
1
|
require_relative 'conditions'
|
4
2
|
require_relative 'parser'
|
5
3
|
|
@@ -9,8 +7,8 @@ module Json
|
|
9
7
|
|
10
8
|
attr_reader :parser
|
11
9
|
|
12
|
-
def initialize(file_io = nil, chunk_size = 1000)
|
13
|
-
@event_generator =
|
10
|
+
def initialize(file_io = nil, chunk_size = 1000, event_generator = :default)
|
11
|
+
@event_generator = make_event_generator(event_generator)
|
14
12
|
|
15
13
|
@file_io = file_io
|
16
14
|
@chunk_size = chunk_size
|
@@ -24,24 +22,39 @@ module Json
|
|
24
22
|
conditions = Conditions.new(yield_level: nesting_level, yield_key: key)
|
25
23
|
conditions.yield_value = ->(aggregator:, value:) { false } unless yield_values
|
26
24
|
|
27
|
-
# TODO: deprecate symbolize_keys and move to initialize
|
28
25
|
@parser = Parser.new(@event_generator, symbolize_keys: symbolize_keys)
|
26
|
+
unyielded_items = []
|
29
27
|
|
30
28
|
parser.get(conditions) do |obj|
|
31
|
-
|
29
|
+
if block_given?
|
30
|
+
yield obj
|
31
|
+
else
|
32
|
+
unyielded_items.push(obj)
|
33
|
+
end
|
34
|
+
|
35
|
+
obj
|
32
36
|
end
|
33
37
|
|
34
38
|
process_io
|
39
|
+
|
40
|
+
unyielded_items
|
35
41
|
end
|
36
42
|
|
37
43
|
def get_with_conditions(conditions, options = {})
|
38
44
|
@parser = Parser.new(@event_generator, symbolize_keys: options[:symbolize_keys])
|
45
|
+
unyielded_items = []
|
39
46
|
|
40
47
|
parser.get(conditions) do |obj|
|
41
|
-
|
48
|
+
if block_given?
|
49
|
+
yield obj
|
50
|
+
else
|
51
|
+
unyielded_items.push(obj)
|
52
|
+
end
|
42
53
|
end
|
43
54
|
|
44
55
|
process_io
|
56
|
+
|
57
|
+
unyielded_items
|
45
58
|
end
|
46
59
|
|
47
60
|
def aggregator
|
@@ -53,6 +66,16 @@ module Json
|
|
53
66
|
def process_io
|
54
67
|
@file_io.each(@chunk_size) { |chunk| parser << chunk } if @file_io
|
55
68
|
end
|
69
|
+
|
70
|
+
def make_event_generator(generator)
|
71
|
+
case generator
|
72
|
+
when :default
|
73
|
+
require 'json/stream'
|
74
|
+
JSON::Stream::Parser.new
|
75
|
+
else
|
76
|
+
generator
|
77
|
+
end
|
78
|
+
end
|
56
79
|
end
|
57
80
|
end
|
58
81
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: json-streamer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- thisismydesign
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-11-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -136,6 +136,20 @@ dependencies:
|
|
136
136
|
- - ">="
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: yajl-ffi
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
139
153
|
- !ruby/object:Gem::Dependency
|
140
154
|
name: json-stream
|
141
155
|
requirement: !ruby/object:Gem::Requirement
|
@@ -197,7 +211,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
197
211
|
version: '0'
|
198
212
|
requirements: []
|
199
213
|
rubyforge_project:
|
200
|
-
rubygems_version: 2.
|
214
|
+
rubygems_version: 2.7.7
|
201
215
|
signing_key:
|
202
216
|
specification_version: 4
|
203
217
|
summary: Utility to support JSON streaming allowing you to get data based on various
|