outstream-json 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bb20f4f2c4d3bd0e47eff8c74a58066c9c0a8ccc
4
+ data.tar.gz: 0145f35292dfb81f1c2f19e7b28b06d507b7cefa
5
+ SHA512:
6
+ metadata.gz: 70215a331d253f1bc969c432dd351e54665d59a60673c8c952ac49c00796440f5028bda6d0680677f6ad0987330c70193d35a88ec6cf51b01c00dbc92d17933b
7
+ data.tar.gz: 2f741ba68be98df355d460a6f97a74862a93a9adc3ef2ead32209df347a3c63c582734d603cf6b254f4b2a2bf5e5030d688608a9f48738c1bf56ea1ff354c8a2
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Ryan Calhoun
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 all
13
+ 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 THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,60 @@
1
+ [![Gem Version](https://badge.fury.io/rb/outstream-json.svg)](http://badge.fury.io/rb/outstream-json)
2
+
3
+ # Outstream::Json
4
+
5
+ A library for producing JSON output in a streaming fashion. It is designed to work with lambdas and lazy enumerators, to minimize the need to create the entire JSON-encoding string at once.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'outstream-json'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install outstream-json
20
+
21
+ ## Usage
22
+
23
+ The Json.create method defines a JSON object
24
+
25
+ out = OutStream::Json.create do
26
+ ...
27
+ end
28
+ # use out.to_s or out.each to product result
29
+
30
+ Use with basic ruby types
31
+
32
+ Outstream::Json.create do
33
+ add string: "hello", number: 42
34
+ add array: [1,2,3]
35
+ end
36
+ # {"string":"hello","number":42,"array":[1,2,3]}
37
+
38
+ Outstream::Json.create do
39
+ add "nested_object" {
40
+ add "foo" => "bar"
41
+ }
42
+ end
43
+ # {"nested_object":{"foo":"bar"}}
44
+
45
+ Use with transformed SQL result set
46
+
47
+ client = Mysql2::Client.new
48
+ results = client.query("SELECT * FROM huge\_table", stream: true)
49
+ Outstream::Json.create do
50
+ add results: results.lazy.map {|row| transform_row(row)}
51
+ end
52
+ # {"results":[{<transformed_result>},...]}
53
+
54
+ ## Contributing
55
+
56
+ 1. Fork it
57
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
58
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
59
+ 4. Push to the branch (`git push origin my-new-feature`)
60
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new {|t|
4
+ t.libs << 'test'
5
+ }
6
+
7
+ desc 'Run tests'
8
+ task :default => :test
@@ -0,0 +1,125 @@
1
+ require 'json'
2
+
3
+ module Outstream
4
+ # Produce a stream of JSON tokens.
5
+ class Json
6
+ # Define an output JSON object, given a block. The block
7
+ # is executed in a context which provides the add method,
8
+ # for adding key-value pairs to the object.
9
+ #
10
+ # Example:
11
+ # Outstream::Json.create do
12
+ # add string: "hello", number: 42
13
+ # add array: [1,2,3]
14
+ # add "nested_object" {
15
+ # add "foo" => "bar"
16
+ # }
17
+ # end
18
+ def self.create(&body_block)
19
+ new body_block
20
+ end
21
+
22
+ # Iterate the output tokens. The block will receive JSON delimeters individually as strings,
23
+ # and string values as quoted strings. If called without a block, returns an enumerator.
24
+ #
25
+ # Example:
26
+ # json.each {|token| puts token}
27
+ def each(&out_block)
28
+ e = Enumerator.new {|yielder|
29
+ Collector.new(yielder).collect &@body_block
30
+ }
31
+
32
+ out_block ? e.each(&out_block) : e
33
+ end
34
+
35
+ # Produce a compact string of the JSON. The entire string is produced at once; this is not
36
+ # suitable for very large JSON output.
37
+ def to_s
38
+ "".tap {|s| each {|str| s.concat str } }
39
+ end
40
+
41
+ private
42
+
43
+ def initialize(body_block)
44
+ @body_block = body_block
45
+ end
46
+
47
+ class Receiver
48
+ def initialize(collector)
49
+ @_collector = collector
50
+ end
51
+ def add(objs, &block)
52
+ @_collector.add objs, &block
53
+ end
54
+ end
55
+
56
+ class Collector
57
+ def initialize(yielder)
58
+ @yielder = yielder
59
+ @count = [0]
60
+ end
61
+ def collect(&block)
62
+ add_object {
63
+ receiver = Receiver.new self
64
+ if block.arity == 1
65
+ block[receiver]
66
+ else
67
+ (class << receiver; self; end).send(:define_method, :__call_block, &block)
68
+ receiver.__call_block
69
+ end
70
+ }
71
+ end
72
+ def write(str)
73
+ @yielder << str
74
+ end
75
+ def add(objs, &block)
76
+ if block
77
+ add_key objs
78
+ add_object &block
79
+ else
80
+ add_to_object objs
81
+ end
82
+ end
83
+ def add_to_object(objs)
84
+ objs.each_pair {|key,val|
85
+ add_key key
86
+ add_value val
87
+ }
88
+ end
89
+ def add_key(key)
90
+ write "," if @count.last > 0
91
+ write key.to_json
92
+ write ":"
93
+ @count[@count.size-1] += 1
94
+ end
95
+ def add_object
96
+ write "{"
97
+ @count.push 0
98
+ result = yield
99
+ @count.pop
100
+ write "}"
101
+
102
+ result
103
+ end
104
+ def add_array(a)
105
+ write "["
106
+ a.enum_for(:each).each_with_index {|v,i|
107
+ write "," if i > 0
108
+ add_value v
109
+ }
110
+ write "]"
111
+ end
112
+ def add_value(value)
113
+ if value.respond_to?:each_pair
114
+ add_object { add_to_object value }
115
+ elsif value.respond_to?:each
116
+ add_array value
117
+ elsif value.respond_to?:call
118
+ add_value value.call
119
+ else
120
+ write value.to_json
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1 @@
1
+ require_relative 'outstream/json'
data/test/test_json.rb ADDED
@@ -0,0 +1,108 @@
1
+ require 'test/unit'
2
+ require 'outstream-json'
3
+
4
+ class TestJson < Test::Unit::TestCase
5
+
6
+ def testScalar
7
+ out = Outstream::Json.create {
8
+ add "foo" => "bar"
9
+ }
10
+ assert_equal '{"foo":"bar"}', out.to_s
11
+ end
12
+ def testScalarWithBlockParam
13
+ out = Outstream::Json.create {|json|
14
+ json.add "foo" => "bar"
15
+ }
16
+ assert_equal '{"foo":"bar"}', out.to_s
17
+ end
18
+ def testMultipleScalars
19
+ out = Outstream::Json.create {
20
+ add "foo" => "bar", "wow" => true
21
+ }
22
+
23
+ assert_equal '{"foo":"bar","wow":true}', out.to_s
24
+ end
25
+ def testArray
26
+ out = Outstream::Json.create {
27
+ add "foo" => [1,2,3]
28
+ }
29
+
30
+ assert_equal '{"foo":[1,2,3]}', out.to_s
31
+ end
32
+ def testHash
33
+ out = Outstream::Json.create {
34
+ add "foo" => {a: 1, b: 2}
35
+ }
36
+ assert_equal '{"foo":{"a":1,"b":2}}', out.to_s
37
+ end
38
+
39
+ def testProc
40
+ out = Outstream::Json.create {
41
+ add "foo" => lambda { "bar" }
42
+ }
43
+ assert_equal '{"foo":"bar"}', out.to_s
44
+ end
45
+ def testProcArray
46
+ out = Outstream::Json.create {
47
+ add "foo" => lambda { [1,2,3] }
48
+ }
49
+ assert_equal '{"foo":[1,2,3]}', out.to_s
50
+ end
51
+ def testProcArrayEach
52
+ out = Outstream::Json.create {
53
+ add "foo" => lambda { [1,2,3].each }
54
+ }
55
+ assert_equal '{"foo":[1,2,3]}', out.to_s
56
+ end
57
+ def testProcHash
58
+ out = Outstream::Json.create {
59
+ add "foo" => lambda { { a: 1, b: 2 } }
60
+ }
61
+ assert_equal '{"foo":{"a":1,"b":2}}', out.to_s
62
+ end
63
+ def testProcHashOfProc
64
+ out = Outstream::Json.create {
65
+ add "foo" => lambda { { a: lambda { 1 }, b: lambda { 2 } } }
66
+ }
67
+ assert_equal '{"foo":{"a":1,"b":2}}', out.to_s
68
+ end
69
+
70
+ def testLocalVariableScope
71
+ x = "bar"
72
+ out = Outstream::Json.create {
73
+ y = "cool"
74
+ add "foo" => x, "wow" => y
75
+ }
76
+ assert_equal '{"foo":"bar","wow":"cool"}', out.to_s
77
+ end
78
+
79
+ def testEnumerator
80
+ x = "fun"
81
+ out = Outstream::Json.create {
82
+ add "foo" => "bar", "wow" => x
83
+ }
84
+ e = out.each
85
+ assert_equal '{', e.next
86
+ assert_equal '"foo"', e.next
87
+ assert_equal ':', e.next
88
+ assert_equal '"bar"', e.next
89
+ assert_equal ',', e.next
90
+ assert_equal '"wow"', e.next
91
+ assert_equal ':', e.next
92
+
93
+ x.upcase!
94
+ assert_equal '"FUN"', e.next
95
+ assert_equal '}', e.next
96
+
97
+ end
98
+
99
+ def testObjectBlock
100
+ out = Outstream::Json.create {
101
+ add "foo" do
102
+ add "bar" => "wow"
103
+ end
104
+ }
105
+ assert_equal '{"foo":{"bar":"wow"}}', out.to_s
106
+ end
107
+ end
108
+
metadata ADDED
@@ -0,0 +1,53 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: outstream-json
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ryan Calhoun
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-02-13 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A library which provides a DSL for writing a large number of object as
14
+ json without building the entire set in memory first.
15
+ email:
16
+ - ryanjamescalhoun@gmail.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - LICENSE.txt
22
+ - README.md
23
+ - Rakefile
24
+ - lib/outstream-json.rb
25
+ - lib/outstream/json.rb
26
+ - test/test_json.rb
27
+ homepage: https://github.com/ryanjamescalhoun/outstream-json
28
+ licenses:
29
+ - MIT
30
+ metadata: {}
31
+ post_install_message:
32
+ rdoc_options: []
33
+ require_paths:
34
+ - lib
35
+ required_ruby_version: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ requirements: []
46
+ rubyforge_project:
47
+ rubygems_version: 2.4.5.1
48
+ signing_key:
49
+ specification_version: 4
50
+ summary: A streaming library for writing large json output
51
+ test_files:
52
+ - test/test_json.rb
53
+ - Rakefile