json-streamer 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +10 -10
- data/.gitmodules +3 -0
- data/CODE_OF_CONDUCT.md +48 -48
- data/Gemfile +4 -4
- data/LICENSE.txt +21 -21
- data/README.md +151 -126
- data/Rakefile +2 -2
- data/bin/console +14 -14
- data/bin/setup +8 -8
- data/json-streamer.gemspec +30 -26
- data/lib/json/streamer.rb +7 -111
- data/lib/json/streamer/json_streamer.rb +107 -0
- data/lib/json/streamer/version.rb +5 -5
- metadata +19 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f04ab89c1174d12704fb5bf27ed2c7663ab6c95
|
4
|
+
data.tar.gz: 95e508c4081e086a58a579d1147ac63d88f86d81
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 612d180722eb1b7c07b4855dc24a5a9971bb6bb8dd20b66743aa06bcf98eee39845c8e313b3f7952c582cd6915571d11a0534ce71a2cf70a1e4ab1d8c54ff1f8
|
7
|
+
data.tar.gz: 48feddeccbadaa95784fe23ebee4bcbbe87dbf27b440ad7f9b10cbac230665be29e005671f304e4d7727e2e06fef6620bb47c5e5601e0af220f3f944de928f34
|
data/.gitignore
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
/.bundle/
|
2
|
-
/.yardoc
|
3
|
-
/Gemfile.lock
|
4
|
-
/_yardoc/
|
5
|
-
/coverage/
|
6
|
-
/doc/
|
7
|
-
/pkg/
|
8
|
-
/spec/reports/
|
9
|
-
/tmp/
|
10
|
-
.idea/*
|
1
|
+
/.bundle/
|
2
|
+
/.yardoc
|
3
|
+
/Gemfile.lock
|
4
|
+
/_yardoc/
|
5
|
+
/coverage/
|
6
|
+
/doc/
|
7
|
+
/pkg/
|
8
|
+
/spec/reports/
|
9
|
+
/tmp/
|
10
|
+
.idea/*
|
data/.gitmodules
ADDED
data/CODE_OF_CONDUCT.md
CHANGED
@@ -1,49 +1,49 @@
|
|
1
|
-
# Contributor Code of Conduct
|
2
|
-
|
3
|
-
As contributors and maintainers of this project, and in the interest of
|
4
|
-
fostering an open and welcoming community, we pledge to respect all people who
|
5
|
-
contribute through reporting issues, posting feature requests, updating
|
6
|
-
documentation, submitting pull requests or patches, and other activities.
|
7
|
-
|
8
|
-
We are committed to making participation in this project a harassment-free
|
9
|
-
experience for everyone, regardless of level of experience, gender, gender
|
10
|
-
identity and expression, sexual orientation, disability, personal appearance,
|
11
|
-
body size, race, ethnicity, age, religion, or nationality.
|
12
|
-
|
13
|
-
Examples of unacceptable behavior by participants include:
|
14
|
-
|
15
|
-
* The use of sexualized language or imagery
|
16
|
-
* Personal attacks
|
17
|
-
* Trolling or insulting/derogatory comments
|
18
|
-
* Public or private harassment
|
19
|
-
* Publishing other's private information, such as physical or electronic
|
20
|
-
addresses, without explicit permission
|
21
|
-
* Other unethical or unprofessional conduct
|
22
|
-
|
23
|
-
Project maintainers have the right and responsibility to remove, edit, or
|
24
|
-
reject comments, commits, code, wiki edits, issues, and other contributions
|
25
|
-
that are not aligned to this Code of Conduct, or to ban temporarily or
|
26
|
-
permanently any contributor for other behaviors that they deem inappropriate,
|
27
|
-
threatening, offensive, or harmful.
|
28
|
-
|
29
|
-
By adopting this Code of Conduct, project maintainers commit themselves to
|
30
|
-
fairly and consistently applying these principles to every aspect of managing
|
31
|
-
this project. Project maintainers who do not follow or enforce the Code of
|
32
|
-
Conduct may be permanently removed from the project team.
|
33
|
-
|
34
|
-
This code of conduct applies both within project spaces and in public spaces
|
35
|
-
when an individual is representing the project or its community.
|
36
|
-
|
37
|
-
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
38
|
-
reported by contacting a project maintainer at csapagyi@users.noreply.github.com. All
|
39
|
-
complaints will be reviewed and investigated and will result in a response that
|
40
|
-
is deemed necessary and appropriate to the circumstances. Maintainers are
|
41
|
-
obligated to maintain confidentiality with regard to the reporter of an
|
42
|
-
incident.
|
43
|
-
|
44
|
-
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
45
|
-
version 1.3.0, available at
|
46
|
-
[http://contributor-covenant.org/version/1/3/0/][version]
|
47
|
-
|
48
|
-
[homepage]: http://contributor-covenant.org
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, and in the interest of
|
4
|
+
fostering an open and welcoming community, we pledge to respect all people who
|
5
|
+
contribute through reporting issues, posting feature requests, updating
|
6
|
+
documentation, submitting pull requests or patches, and other activities.
|
7
|
+
|
8
|
+
We are committed to making participation in this project a harassment-free
|
9
|
+
experience for everyone, regardless of level of experience, gender, gender
|
10
|
+
identity and expression, sexual orientation, disability, personal appearance,
|
11
|
+
body size, race, ethnicity, age, religion, or nationality.
|
12
|
+
|
13
|
+
Examples of unacceptable behavior by participants include:
|
14
|
+
|
15
|
+
* The use of sexualized language or imagery
|
16
|
+
* Personal attacks
|
17
|
+
* Trolling or insulting/derogatory comments
|
18
|
+
* Public or private harassment
|
19
|
+
* Publishing other's private information, such as physical or electronic
|
20
|
+
addresses, without explicit permission
|
21
|
+
* Other unethical or unprofessional conduct
|
22
|
+
|
23
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
24
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
25
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
26
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
27
|
+
threatening, offensive, or harmful.
|
28
|
+
|
29
|
+
By adopting this Code of Conduct, project maintainers commit themselves to
|
30
|
+
fairly and consistently applying these principles to every aspect of managing
|
31
|
+
this project. Project maintainers who do not follow or enforce the Code of
|
32
|
+
Conduct may be permanently removed from the project team.
|
33
|
+
|
34
|
+
This code of conduct applies both within project spaces and in public spaces
|
35
|
+
when an individual is representing the project or its community.
|
36
|
+
|
37
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
38
|
+
reported by contacting a project maintainer at csapagyi@users.noreply.github.com. All
|
39
|
+
complaints will be reviewed and investigated and will result in a response that
|
40
|
+
is deemed necessary and appropriate to the circumstances. Maintainers are
|
41
|
+
obligated to maintain confidentiality with regard to the reporter of an
|
42
|
+
incident.
|
43
|
+
|
44
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
45
|
+
version 1.3.0, available at
|
46
|
+
[http://contributor-covenant.org/version/1/3/0/][version]
|
47
|
+
|
48
|
+
[homepage]: http://contributor-covenant.org
|
49
49
|
[version]: http://contributor-covenant.org/version/1/3/0/
|
data/Gemfile
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
source 'https://rubygems.org'
|
2
|
-
|
3
|
-
# Specify your gem's dependencies in json-streamer.gemspec
|
4
|
-
gemspec
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in json-streamer.gemspec
|
4
|
+
gemspec
|
data/LICENSE.txt
CHANGED
@@ -1,21 +1,21 @@
|
|
1
|
-
The MIT License (MIT)
|
2
|
-
|
3
|
-
Copyright (c) 2016 Csaba Apagyi
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
7
|
-
in the Software without restriction, including without limitation the rights
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
10
|
-
furnished to do so, subject to the following conditions:
|
11
|
-
|
12
|
-
The above copyright notice and this permission notice shall be included in
|
13
|
-
all copies or substantial portions of the Software.
|
14
|
-
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
-
THE SOFTWARE.
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Csaba Apagyi
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,126 +1,151 @@
|
|
1
|
-
# Json::Streamer
|
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
|
-
```json
|
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
|
-
|
1
|
+
# Json::Streamer
|
2
|
+
|
3
|
+
Ruby utility that supports JSON streaming allowing you to get data based on various criteria (key, nesting level, etc).
|
4
|
+
|
5
|
+
*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)):*
|
6
|
+
|
7
|
+
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.).
|
8
|
+
|
9
|
+
|
10
|
+
*If you're new to this:*
|
11
|
+
|
12
|
+
Streaming is useful for
|
13
|
+
- big files that do not fit in the memory (or you'd rather avoid the risk)
|
14
|
+
- files read in chunks (e.g. arriving over network)
|
15
|
+
- cases where you expect some issue with the file (e.g. losing connection to source, invalid data at some point) but would like to get as much data as possible anyway
|
16
|
+
|
17
|
+
This gem is aimed at making streaming as easy and convenient as possible.
|
18
|
+
|
19
|
+
*Performance:*
|
20
|
+
|
21
|
+
The gem uses JSON::Stream's events in the background. It was chosen because it's a pure Ruby parser.
|
22
|
+
A similar implementation can be done using the ~10 times faster Yajl::FFI gem that is dependent on the native YAJL library.
|
23
|
+
I did not measure the performance of my implementation on top of these libraries.
|
24
|
+
|
25
|
+
## Installation
|
26
|
+
|
27
|
+
Add this line to your application's Gemfile:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
gem 'json-streamer'
|
31
|
+
```
|
32
|
+
|
33
|
+
And then execute:
|
34
|
+
|
35
|
+
$ bundle
|
36
|
+
|
37
|
+
Or install it yourself as:
|
38
|
+
|
39
|
+
$ gem install json-streamer
|
40
|
+
|
41
|
+
## Usage
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
require 'json/streamer'
|
45
|
+
|
46
|
+
file_stream = File.open('data.json', 'r')
|
47
|
+
|
48
|
+
# Get a JsonStreamer object that will parse file_stream by chunks of 500
|
49
|
+
# Default chunk size in 1000
|
50
|
+
streamer = Json::Streamer::JsonStreamer.new(file_stream, 500)
|
51
|
+
```
|
52
|
+
|
53
|
+
#### Get objects based on nesting level
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
# Level zero will give you the full JSON, first level will give you data within full JSON object, etc.
|
57
|
+
streamer.get(nesting_level:1) do |object|
|
58
|
+
p object
|
59
|
+
end
|
60
|
+
```
|
61
|
+
|
62
|
+
Input:
|
63
|
+
```json
|
64
|
+
{
|
65
|
+
"object1": "first_level_value",
|
66
|
+
"object2": {}
|
67
|
+
}
|
68
|
+
```
|
69
|
+
|
70
|
+
Output:
|
71
|
+
```json
|
72
|
+
"first_level_value"
|
73
|
+
{}
|
74
|
+
```
|
75
|
+
|
76
|
+
#### Get data based on key
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
streamer.get(key:'desired_key') do |object|
|
80
|
+
p object
|
81
|
+
end
|
82
|
+
```
|
83
|
+
|
84
|
+
Input:
|
85
|
+
```json
|
86
|
+
{
|
87
|
+
"obj1" : {
|
88
|
+
"desired_key" : "value1"
|
89
|
+
},
|
90
|
+
"desired_key" : "value2",
|
91
|
+
"obj2" : {
|
92
|
+
"desired_key" : {
|
93
|
+
"desired_key" : "value3"
|
94
|
+
}
|
95
|
+
}
|
96
|
+
}
|
97
|
+
```
|
98
|
+
|
99
|
+
Output:
|
100
|
+
```json
|
101
|
+
"value1"
|
102
|
+
"value2"
|
103
|
+
"value3"
|
104
|
+
{"desired_key" : "value3"}
|
105
|
+
```
|
106
|
+
|
107
|
+
#### Skip values if you'd only like to get objects and arrays
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
streamer.get(nesting_level:1, yield_values:false) do |object|
|
111
|
+
p object
|
112
|
+
end
|
113
|
+
```
|
114
|
+
|
115
|
+
Input:
|
116
|
+
```json
|
117
|
+
{
|
118
|
+
"obj1" : {},
|
119
|
+
"key" : "value"
|
120
|
+
}
|
121
|
+
```
|
122
|
+
|
123
|
+
Output:
|
124
|
+
```json
|
125
|
+
{}
|
126
|
+
```
|
127
|
+
|
128
|
+
Check the unit tests for more examples ([spec/streamer_spec.rb](spec/streamer_spec.rb)).
|
129
|
+
|
130
|
+
## Feedback
|
131
|
+
|
132
|
+
Any feedback is much appreciated.
|
133
|
+
|
134
|
+
I can only tailor this project to fit use-cases I know about - which are usually my own ones. If you find that this might be the right direction to solve your problem too but you find that it's suboptimal or lacks features don't hesitate to contact me.
|
135
|
+
|
136
|
+
Please let me know if you make use of this project so that I can prioritize further efforts.
|
137
|
+
|
138
|
+
## Development
|
139
|
+
|
140
|
+
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
141
|
+
|
142
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
143
|
+
|
144
|
+
## Contributing
|
145
|
+
|
146
|
+
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.
|
147
|
+
|
148
|
+
|
149
|
+
## License
|
150
|
+
|
151
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
require "bundler/gem_tasks"
|
2
|
-
task :default => :spec
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
task :default => :spec
|
data/bin/console
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require "bundler/setup"
|
4
|
-
require "json/streamer"
|
5
|
-
|
6
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
-
# with your gem easier. You can also use a different console, if you like.
|
8
|
-
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
# require "pry"
|
11
|
-
# Pry.start
|
12
|
-
|
13
|
-
require "irb"
|
14
|
-
IRB.start
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "json/streamer"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
#!/usr/bin/env bash
|
2
|
-
set -euo pipefail
|
3
|
-
IFS=$'\n\t'
|
4
|
-
set -vx
|
5
|
-
|
6
|
-
bundle install
|
7
|
-
|
8
|
-
# Do any other automated setup that you need to do here
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
set -euo pipefail
|
3
|
+
IFS=$'\n\t'
|
4
|
+
set -vx
|
5
|
+
|
6
|
+
bundle install
|
7
|
+
|
8
|
+
# Do any other automated setup that you need to do here
|
data/json-streamer.gemspec
CHANGED
@@ -1,26 +1,30 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'json/streamer/version'
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = "json-streamer"
|
8
|
-
spec.version = Json::Streamer::VERSION
|
9
|
-
spec.authors = ["
|
10
|
-
spec.email = ["
|
11
|
-
|
12
|
-
spec.summary = %q{Utility to support JSON streaming allowing you to get data based on various criteria (key, nesting level, etc)}
|
13
|
-
spec.homepage = "https://github.com/
|
14
|
-
spec.license = "MIT"
|
15
|
-
|
16
|
-
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
-
spec.bindir = "exe"
|
18
|
-
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
|
-
spec.require_paths = ["lib"]
|
20
|
-
|
21
|
-
|
22
|
-
spec.
|
23
|
-
|
24
|
-
spec.add_development_dependency "
|
25
|
-
spec.add_development_dependency "
|
26
|
-
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'json/streamer/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "json-streamer"
|
8
|
+
spec.version = Json::Streamer::VERSION
|
9
|
+
spec.authors = ["thisismydesign"]
|
10
|
+
spec.email = ["thisismydesign@users.noreply.github.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Utility to support JSON streaming allowing you to get data based on various criteria (key, nesting level, etc)}
|
13
|
+
spec.homepage = "https://github.com/thisismydesign/json-streamer"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = "exe"
|
18
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# Because of `require_relative`
|
22
|
+
spec.required_ruby_version = '>= 1.9.2'
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.14"
|
25
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
26
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
27
|
+
spec.add_development_dependency "ndhash"
|
28
|
+
|
29
|
+
spec.add_dependency "json-stream"
|
30
|
+
end
|
data/lib/json/streamer.rb
CHANGED
@@ -1,111 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
module
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
attr_reader :aggregator
|
9
|
-
|
10
|
-
def initialize(file_io, chunk_size = 1000)
|
11
|
-
@parser = JSON::Stream::Parser.new
|
12
|
-
|
13
|
-
@file_io = file_io
|
14
|
-
@chunk_size = chunk_size
|
15
|
-
|
16
|
-
@current_nesting_level = -1
|
17
|
-
@current_key = nil
|
18
|
-
@aggregator = {}
|
19
|
-
@temp_aggregator_keys = {}
|
20
|
-
|
21
|
-
@parser.start_object {start_object}
|
22
|
-
@parser.start_array {start_array}
|
23
|
-
@parser.key {|k| key(k)}
|
24
|
-
|
25
|
-
end
|
26
|
-
|
27
|
-
# Callbacks containing yield has be defined in the method called via block
|
28
|
-
def get(nesting_level:-1, key:nil, yield_values:true)
|
29
|
-
@yield_nesting_level = nesting_level
|
30
|
-
@wanted_key = key
|
31
|
-
@yield_values = yield_values
|
32
|
-
|
33
|
-
@parser.value do |v|
|
34
|
-
if @aggregator[@current_nesting_level].kind_of? Array
|
35
|
-
@aggregator[@current_nesting_level] << v
|
36
|
-
else
|
37
|
-
@aggregator[@current_nesting_level][@current_key] = v
|
38
|
-
if @yield_values and yield_value?
|
39
|
-
yield v
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
@parser.end_object do
|
45
|
-
if yield_object?
|
46
|
-
yield @aggregator[@current_nesting_level].clone
|
47
|
-
# TODO probably can be faster than reject!{true}
|
48
|
-
@aggregator[@current_nesting_level].reject!{true}
|
49
|
-
else
|
50
|
-
merge_up
|
51
|
-
end
|
52
|
-
|
53
|
-
@current_nesting_level -= 1
|
54
|
-
end
|
55
|
-
|
56
|
-
@parser.end_array do
|
57
|
-
if yield_object?
|
58
|
-
yield @aggregator[@current_nesting_level].clone
|
59
|
-
# TODO probably can be faster than reject!{true}
|
60
|
-
@aggregator[@current_nesting_level].reject!{true}
|
61
|
-
else
|
62
|
-
merge_up
|
63
|
-
end
|
64
|
-
|
65
|
-
@current_nesting_level -= 1
|
66
|
-
end
|
67
|
-
|
68
|
-
@file_io.each(@chunk_size) do |chunk|
|
69
|
-
@parser << chunk
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def yield_object?
|
74
|
-
@current_nesting_level.eql? @yield_nesting_level or (not @wanted_key.nil? and @wanted_key == @temp_aggregator_keys[@current_nesting_level-1])
|
75
|
-
end
|
76
|
-
|
77
|
-
def yield_value?
|
78
|
-
(@current_nesting_level + 1).eql? @yield_nesting_level or @wanted_key == @current_key
|
79
|
-
end
|
80
|
-
|
81
|
-
def start_object
|
82
|
-
@temp_aggregator_keys[@current_nesting_level] = @current_key
|
83
|
-
@current_nesting_level += 1
|
84
|
-
@aggregator[@current_nesting_level] = {}
|
85
|
-
end
|
86
|
-
|
87
|
-
def start_array
|
88
|
-
@temp_aggregator_keys[@current_nesting_level] = @current_key
|
89
|
-
@current_nesting_level += 1
|
90
|
-
@aggregator[@current_nesting_level] = []
|
91
|
-
end
|
92
|
-
|
93
|
-
def key(k)
|
94
|
-
@current_key = k
|
95
|
-
end
|
96
|
-
|
97
|
-
def merge_up
|
98
|
-
return if @current_nesting_level == 0
|
99
|
-
previous_nesting_level = @current_nesting_level - 1
|
100
|
-
if @aggregator[previous_nesting_level].kind_of? Array
|
101
|
-
@aggregator[previous_nesting_level] << @aggregator[@current_nesting_level]
|
102
|
-
else
|
103
|
-
@aggregator[previous_nesting_level][@temp_aggregator_keys[previous_nesting_level]] = @aggregator[@current_nesting_level]
|
104
|
-
end
|
105
|
-
|
106
|
-
@aggregator.delete(@current_nesting_level)
|
107
|
-
@aggregator
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
1
|
+
require_relative "streamer/json_streamer"
|
2
|
+
|
3
|
+
module Json
|
4
|
+
module Streamer
|
5
|
+
|
6
|
+
end
|
7
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require "json/stream"
|
2
|
+
|
3
|
+
module Json
|
4
|
+
module Streamer
|
5
|
+
class JsonStreamer
|
6
|
+
|
7
|
+
attr_reader :aggregator
|
8
|
+
|
9
|
+
def initialize(file_io, chunk_size = 1000)
|
10
|
+
@parser = JSON::Stream::Parser.new
|
11
|
+
|
12
|
+
@file_io = file_io
|
13
|
+
@chunk_size = chunk_size
|
14
|
+
|
15
|
+
@current_nesting_level = -1
|
16
|
+
@current_key = nil
|
17
|
+
@aggregator = {}
|
18
|
+
@temp_aggregator_keys = {}
|
19
|
+
|
20
|
+
@parser.start_object {start_object}
|
21
|
+
@parser.start_array {start_array}
|
22
|
+
@parser.key {|k| key(k)}
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
# Callbacks containing `yield` have to be defined in the method called via block otherwise yield won't work
|
27
|
+
def get(nesting_level:-1, key:nil, yield_values:true)
|
28
|
+
yield_nesting_level = nesting_level
|
29
|
+
wanted_key = key
|
30
|
+
|
31
|
+
@parser.value do |v|
|
32
|
+
if @aggregator[@current_nesting_level].kind_of? Array
|
33
|
+
@aggregator[@current_nesting_level] << v
|
34
|
+
else
|
35
|
+
@aggregator[@current_nesting_level][@current_key] = v
|
36
|
+
if yield_values and yield_value?(yield_nesting_level, wanted_key)
|
37
|
+
yield v
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
@parser.end_object do
|
43
|
+
if yield_object?(yield_nesting_level, wanted_key)
|
44
|
+
yield @aggregator[@current_nesting_level].clone
|
45
|
+
@aggregator[@current_nesting_level] = {}
|
46
|
+
else
|
47
|
+
merge_up
|
48
|
+
end
|
49
|
+
|
50
|
+
@current_nesting_level -= 1
|
51
|
+
end
|
52
|
+
|
53
|
+
@parser.end_array do
|
54
|
+
if yield_object?(yield_nesting_level, wanted_key)
|
55
|
+
yield @aggregator[@current_nesting_level].clone
|
56
|
+
@aggregator[@current_nesting_level] = []
|
57
|
+
else
|
58
|
+
merge_up
|
59
|
+
end
|
60
|
+
|
61
|
+
@current_nesting_level -= 1
|
62
|
+
end
|
63
|
+
|
64
|
+
@file_io.each(@chunk_size) do |chunk|
|
65
|
+
@parser << chunk
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def yield_object?(yield_nesting_level, wanted_key)
|
70
|
+
@current_nesting_level.eql? yield_nesting_level or (not wanted_key.nil? and wanted_key == @temp_aggregator_keys[@current_nesting_level-1])
|
71
|
+
end
|
72
|
+
|
73
|
+
def yield_value?(yield_nesting_level, wanted_key)
|
74
|
+
(@current_nesting_level + 1).eql? yield_nesting_level or wanted_key == @current_key
|
75
|
+
end
|
76
|
+
|
77
|
+
def start_object
|
78
|
+
@temp_aggregator_keys[@current_nesting_level] = @current_key
|
79
|
+
@current_nesting_level += 1
|
80
|
+
@aggregator[@current_nesting_level] = {}
|
81
|
+
end
|
82
|
+
|
83
|
+
def start_array
|
84
|
+
@temp_aggregator_keys[@current_nesting_level] = @current_key
|
85
|
+
@current_nesting_level += 1
|
86
|
+
@aggregator[@current_nesting_level] = []
|
87
|
+
end
|
88
|
+
|
89
|
+
def key(k)
|
90
|
+
@current_key = k
|
91
|
+
end
|
92
|
+
|
93
|
+
def merge_up
|
94
|
+
return if @current_nesting_level == 0
|
95
|
+
previous_nesting_level = @current_nesting_level - 1
|
96
|
+
if @aggregator[previous_nesting_level].kind_of? Array
|
97
|
+
@aggregator[previous_nesting_level] << @aggregator[@current_nesting_level]
|
98
|
+
else
|
99
|
+
@aggregator[previous_nesting_level][@temp_aggregator_keys[previous_nesting_level]] = @aggregator[@current_nesting_level]
|
100
|
+
end
|
101
|
+
|
102
|
+
@aggregator.delete(@current_nesting_level)
|
103
|
+
@aggregator
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
module Json
|
2
|
-
module Streamer
|
3
|
-
VERSION = "0.
|
4
|
-
end
|
5
|
-
end
|
1
|
+
module Json
|
2
|
+
module Streamer
|
3
|
+
VERSION = "0.6.0"
|
4
|
+
end
|
5
|
+
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: 0.
|
4
|
+
version: 0.6.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: 2017-04-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.
|
19
|
+
version: '1.14'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1.
|
26
|
+
version: '1.14'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -39,21 +39,21 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '10.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
47
|
+
version: '3.0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
54
|
+
version: '3.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: ndhash
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - ">="
|
@@ -67,13 +67,13 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: json-stream
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
|
-
type: :
|
76
|
+
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
@@ -82,12 +82,13 @@ dependencies:
|
|
82
82
|
version: '0'
|
83
83
|
description:
|
84
84
|
email:
|
85
|
-
-
|
85
|
+
- thisismydesign@users.noreply.github.com
|
86
86
|
executables: []
|
87
87
|
extensions: []
|
88
88
|
extra_rdoc_files: []
|
89
89
|
files:
|
90
90
|
- ".gitignore"
|
91
|
+
- ".gitmodules"
|
91
92
|
- CODE_OF_CONDUCT.md
|
92
93
|
- Gemfile
|
93
94
|
- LICENSE.txt
|
@@ -97,8 +98,9 @@ files:
|
|
97
98
|
- bin/setup
|
98
99
|
- json-streamer.gemspec
|
99
100
|
- lib/json/streamer.rb
|
101
|
+
- lib/json/streamer/json_streamer.rb
|
100
102
|
- lib/json/streamer/version.rb
|
101
|
-
homepage: https://github.com/
|
103
|
+
homepage: https://github.com/thisismydesign/json-streamer
|
102
104
|
licenses:
|
103
105
|
- MIT
|
104
106
|
metadata: {}
|
@@ -110,7 +112,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
110
112
|
requirements:
|
111
113
|
- - ">="
|
112
114
|
- !ruby/object:Gem::Version
|
113
|
-
version:
|
115
|
+
version: 1.9.2
|
114
116
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
115
117
|
requirements:
|
116
118
|
- - ">="
|
@@ -118,7 +120,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
118
120
|
version: '0'
|
119
121
|
requirements: []
|
120
122
|
rubyforge_project:
|
121
|
-
rubygems_version: 2.5.
|
123
|
+
rubygems_version: 2.5.2
|
122
124
|
signing_key:
|
123
125
|
specification_version: 4
|
124
126
|
summary: Utility to support JSON streaming allowing you to get data based on various
|