jsonify 0.0.2 → 0.0.3
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.
- data/README.md +15 -15
- data/lib/jsonify/builder.rb +77 -79
- data/lib/jsonify/version.rb +1 -1
- data/spec/builder_spec.rb +42 -53
- metadata +4 -4
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Jsonify
|
1
|
+
# Jsonify -- a builder for JSON <a href="http://travis-ci.org/bsiggelkow/jsonify"><img src="https://secure.travis-ci.org/bsiggelkow/jsonify.png" alt=""></a>
|
2
2
|
|
3
3
|
[Jsonify](https://github.com/bsiggelkow/jsonify) is to JSON as [Builder](https://github.com/jimweirich/builder) is to XML.
|
4
4
|
|
@@ -19,18 +19,15 @@ Nevertheless, this forces the developer to place this code into the model when i
|
|
19
19
|
|
20
20
|
When someone asks "Where are the model representations defined?", I don't want to have to say "Well, look in the views folder for XML, but you have to look at the code in the model for the JSON format."
|
21
21
|
|
22
|
-
There are other
|
23
|
-
|
22
|
+
There are a number of <a href='#related'>other libraries</a> available that try to solve this problem. Some take a similar approach to Jsonify and provide a builder-style interface.
|
23
|
+
Others allow the developer to specify the representation using a common DSL that can generate both JSON and XML.
|
24
|
+
Please take a look at these projects when you consider alternatives. It's my opinion that there are substantial and inherent differences between XML and JSON; and that these differences may force the developer to make concessions in one format or the other.
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
But an even greater motivation for me was emulating the simplicity of Builder. I have not found a single framework for JSON that provides the simplicity and elegance of Builder. Jsonify is my attempt at remedying that situation.
|
28
|
-
|
29
|
-
___more coming soon___
|
26
|
+
But an even greater motivation for me was emulating the simplicity of [Builder](https://github.com/jimweirich/builder). I have not found a single framework for JSON that provides the simplicity and elegance of Builder. Jsonify is my attempt at remedying that situation.
|
30
27
|
|
31
28
|
## Installation
|
32
29
|
|
33
|
-
gem install jsonify
|
30
|
+
`gem install jsonify`
|
34
31
|
|
35
32
|
## Usage
|
36
33
|
|
@@ -82,7 +79,7 @@ Results in ...
|
|
82
79
|
|
83
80
|
### View Templates
|
84
81
|
|
85
|
-
Jsonify includes Rails 3 template handler. Rails will handle any template with a
|
82
|
+
Jsonify includes Rails 3 template handler. Rails will handle any template with a `.jsonify` extension with Jsonify.
|
86
83
|
The Jsonify template handler exposes the `Jsonify::Builder` instance to your template with the `json` variable as in the following example:
|
87
84
|
|
88
85
|
json.hello do
|
@@ -91,15 +88,18 @@ The Jsonify template handler exposes the `Jsonify::Builder` instance to your tem
|
|
91
88
|
|
92
89
|
## Documentation
|
93
90
|
|
94
|
-
[
|
95
|
-
|
96
|
-
## Build Status
|
91
|
+
[Yard Docs](http://rubydoc.info/github/bsiggelkow/jsonify/master/frames)
|
97
92
|
|
98
|
-
|
93
|
+
<a name='related'/>
|
94
|
+
<h2>Related Projects</h2>
|
95
|
+
- [Argonaut](https://github.com/jbr/argonaut)
|
96
|
+
- [JSON Builder](https://github.com/dewski/json_builder)
|
97
|
+
- [RABL](https://github.com/nesquena/rabl)
|
98
|
+
- [Tokamak](https://github.com/abril/tokamak)
|
99
99
|
|
100
100
|
## TODOs
|
101
|
-
1. Consider simplified means of creating arrays (e.g. json.links(@links) {|link| ...})
|
102
101
|
1. Benchmark performance
|
102
|
+
1. Document how partials can be used
|
103
103
|
|
104
104
|
## Roadmap
|
105
105
|
|
data/lib/jsonify/builder.rb
CHANGED
@@ -40,43 +40,93 @@ module Jsonify
|
|
40
40
|
@pretty ? JSON.pretty_generate(JSON.parse(result)) : result
|
41
41
|
end
|
42
42
|
|
43
|
-
#
|
44
|
-
# @param
|
45
|
-
|
46
|
-
|
43
|
+
# Stores the key and value into a JSON object
|
44
|
+
# @param key the key for the pair
|
45
|
+
# @param value the value for the pair
|
46
|
+
# @return self to allow for chaining
|
47
|
+
def store!(key, value=nil)
|
48
|
+
(@stack[@level] ||= JsonObject.new).add(key,value)
|
49
|
+
self
|
47
50
|
end
|
51
|
+
|
52
|
+
alias_method :[]=, :store!
|
48
53
|
|
49
|
-
|
54
|
+
# Append -- pushes the given object on the end of a JsonArray.
|
55
|
+
def <<(val)
|
56
|
+
__append(val)
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
60
|
+
# Append -- pushes the given variable list objects on to the end of the JsonArray
|
61
|
+
def append!(*args)
|
62
|
+
args.each do |arg|
|
63
|
+
__append( arg )
|
64
|
+
end
|
65
|
+
self
|
66
|
+
end
|
50
67
|
|
51
|
-
# Adds a new JsonPair to the builder
|
52
|
-
#
|
68
|
+
# Adds a new JsonPair to the builder where the key of the pair is set to the method name
|
69
|
+
# (`sym`).
|
70
|
+
# When passed a block, the value of the pair is set to the result of that
|
71
|
+
# block; otherwise, the value is set to the argument(s) (`args`).
|
72
|
+
#
|
73
|
+
# @example Create an object literal
|
74
|
+
# json.person do
|
75
|
+
# json.first_name @person.given_name
|
76
|
+
# json.last_name @person.surname
|
77
|
+
# end
|
78
|
+
#
|
79
|
+
# @example compiles to something like ...
|
80
|
+
# "person": {
|
81
|
+
# "first_name": "George",
|
82
|
+
# "last_name": "Burdell"
|
83
|
+
# }
|
84
|
+
#
|
85
|
+
# If a block is given and an argument is passed, the argument it is assumed to be an
|
86
|
+
# Array (more specifically, an object that responds to `each`).
|
87
|
+
# The argument is iterated over and each item is yielded to the block.
|
88
|
+
# The result of the block becomes an array item of a JsonArray.
|
89
|
+
#
|
90
|
+
# @example Map an of array of links to an array of JSON objects
|
91
|
+
# json.links(@links) do |link|
|
92
|
+
# {:rel => link.first, :href => link.last}
|
93
|
+
# end
|
94
|
+
#
|
95
|
+
# @example compiles to something like ...
|
96
|
+
# "links": [
|
97
|
+
# {
|
98
|
+
# "rel": "self",
|
99
|
+
# "href": "http://example.com/people/123"
|
100
|
+
# },
|
101
|
+
# {
|
102
|
+
# "rel": "school",
|
103
|
+
# "href": "http://gatech.edu"
|
104
|
+
# }
|
105
|
+
# ]
|
53
106
|
#
|
54
107
|
# @param *args [Array] iterates over the given array yielding each array item to the block; the result of which is added to a JsonArray
|
55
108
|
def method_missing(sym, *args, &block)
|
56
109
|
|
57
110
|
# When no block given, simply add the symbol and arg as key - value for a JsonPair to current
|
58
|
-
return
|
111
|
+
return __store( sym, args.length > 1 ? args : args.first ) unless block
|
59
112
|
|
60
|
-
#
|
61
|
-
pair = Generate.pair_value(sym)
|
62
|
-
|
113
|
+
# In a block; create a JSON pair (with no value) and add it to the current object
|
114
|
+
pair = Generate.pair_value(sym)
|
115
|
+
__store pair
|
63
116
|
|
64
117
|
# Now process the block
|
65
118
|
@level += 1
|
66
119
|
|
67
|
-
|
68
|
-
|
69
|
-
|
120
|
+
if args.empty?
|
121
|
+
block.call
|
122
|
+
else
|
70
123
|
args.first.each do |arg|
|
71
|
-
|
124
|
+
__append block.call(arg)
|
72
125
|
end
|
73
|
-
else
|
74
|
-
# No argument was given; ordinary JsonObject is expected
|
75
|
-
block.call(self)
|
76
126
|
end
|
77
127
|
|
78
|
-
# Set the value on the pair to
|
79
|
-
pair.value =
|
128
|
+
# Set the value on the pair to the object at the top of the stack
|
129
|
+
pair.value = @stack[@level]
|
80
130
|
|
81
131
|
# Pop current off the top of the stack; we are done with it at this point
|
82
132
|
@stack.pop
|
@@ -84,69 +134,17 @@ module Jsonify
|
|
84
134
|
@level -= 1
|
85
135
|
end
|
86
136
|
|
87
|
-
# Sets the object at the top of the stack to a new JsonObject, which is yielded to the block.
|
88
|
-
def object!
|
89
|
-
__set_current JsonObject.new
|
90
|
-
yield __current
|
91
|
-
end
|
92
|
-
|
93
|
-
# Sets the object at the top of the stack to a new JsonArray, which is yielded to the block.
|
94
|
-
def array!
|
95
|
-
__set_current JsonArray.new
|
96
|
-
@level += 1
|
97
|
-
yield @stack[@level-1]
|
98
|
-
@level -= 1
|
99
|
-
__current
|
100
|
-
end
|
101
|
-
|
102
|
-
# Maps each element in the given array to a JsonArray. The result of the block becomes an array item of the JsonArray.
|
103
|
-
# @param array array of objects to iterate over.
|
104
|
-
#
|
105
|
-
# @example Map an of array of links to an array of JSON objects
|
106
|
-
# json.links do
|
107
|
-
# json.map!(links) do |link|
|
108
|
-
# {:rel => link.first, :href => link.last}
|
109
|
-
# end
|
110
|
-
# end
|
111
|
-
#
|
112
|
-
# @example compiles to something like ...
|
113
|
-
# "links": [
|
114
|
-
# {
|
115
|
-
# "rel": "self",
|
116
|
-
# "href": "http://example.com/people/123"
|
117
|
-
# },
|
118
|
-
# {
|
119
|
-
# "rel": "school",
|
120
|
-
# "href": "http://gatech.edu"
|
121
|
-
# }
|
122
|
-
# ]
|
123
|
-
def map!(array)
|
124
|
-
__set_current JsonArray.new
|
125
|
-
array.each do |item|
|
126
|
-
__current << (yield item)
|
127
|
-
end
|
128
|
-
__current
|
129
|
-
end
|
130
|
-
|
131
|
-
alias_method :collect!, :map!
|
132
|
-
|
133
137
|
private
|
134
138
|
|
135
|
-
#
|
139
|
+
# BlankSlate requires the __<method> names
|
136
140
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
def __current
|
141
|
-
@stack[@level] ||= JsonObject.new
|
142
|
-
end
|
141
|
+
def __store(key,value=nil)
|
142
|
+
(@stack[@level] ||= JsonObject.new).add(key,value)
|
143
|
+
end
|
143
144
|
|
144
|
-
|
145
|
-
|
146
|
-
# @param val object to set at the top of the stack
|
147
|
-
def __set_current(val)
|
148
|
-
@stack[@level] = val
|
145
|
+
def __append(value)
|
146
|
+
(@stack[@level] ||= JsonArray.new).add value
|
149
147
|
end
|
150
|
-
|
148
|
+
|
151
149
|
end
|
152
150
|
end
|
data/lib/jsonify/version.rb
CHANGED
data/spec/builder_spec.rb
CHANGED
@@ -63,46 +63,59 @@ PRETTY_JSON
|
|
63
63
|
json.compile!.should == pretty_results.chomp
|
64
64
|
end
|
65
65
|
end
|
66
|
+
|
67
|
+
describe 'array creation' do
|
68
|
+
it 'with the append operator (<<)' do
|
69
|
+
json << 1 << 2
|
70
|
+
json.compile!.should == "[1,2]"
|
71
|
+
end
|
72
|
+
it 'with the append! method' do
|
73
|
+
json.append!( 1,2 )
|
74
|
+
.append! 3
|
75
|
+
json.compile!.should == "[1,2,3]"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
describe 'object creation' do
|
79
|
+
it 'should support the element assignment operator( []= )' do
|
80
|
+
json["foo"] = 'bar'
|
81
|
+
json.compile!.should == '{"foo":"bar"}'
|
82
|
+
end
|
83
|
+
it 'should support the store! message' do
|
84
|
+
json.store!( "foo", "bar" )
|
85
|
+
.store!( 'no', "whar" )
|
86
|
+
json.compile!.should == '{"foo":"bar","no":"whar"}'
|
87
|
+
end
|
88
|
+
end
|
66
89
|
end
|
67
90
|
|
68
91
|
describe 'arrays' do
|
69
92
|
it 'simple array should work' do
|
70
|
-
json
|
71
|
-
|
72
|
-
ary << 2
|
73
|
-
end
|
93
|
+
json << 1
|
94
|
+
json << 2
|
74
95
|
json.compile!.should == "[1,2]"
|
75
96
|
end
|
76
97
|
it 'array of arrays should work' do
|
77
|
-
json
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
end
|
82
|
-
json.compile!.should == "[[1],[2],3]"
|
98
|
+
json << [1]
|
99
|
+
json << [2]
|
100
|
+
json << [3]
|
101
|
+
json.compile!.should == "[[1],[2],[3]]"
|
83
102
|
end
|
84
103
|
it 'array of hashes should work' do
|
85
|
-
json
|
86
|
-
|
87
|
-
ary << {:go => :far}
|
88
|
-
end
|
104
|
+
json << {:foo => :bar}
|
105
|
+
json << {:go => :far}
|
89
106
|
json.compile!.should == "[{\"foo\":\"bar\"},{\"go\":\"far\"}]"
|
90
107
|
end
|
91
108
|
end
|
92
109
|
|
93
110
|
describe 'objects' do
|
94
111
|
it 'simple object should work' do
|
95
|
-
json.
|
96
|
-
|
97
|
-
obj.add :go, :far
|
98
|
-
end
|
112
|
+
json.foo :bar
|
113
|
+
json.go :far
|
99
114
|
json.compile!.should == "{\"foo\":\"bar\",\"go\":\"far\"}"
|
100
115
|
end
|
101
116
|
it 'should handle arrays' do
|
102
|
-
json
|
103
|
-
|
104
|
-
obj.add 4, 5
|
105
|
-
end
|
117
|
+
json[1] = [2, 3]
|
118
|
+
json[4] = 5
|
106
119
|
json.compile!.should == '{"1":[2,3],"4":5}'
|
107
120
|
end
|
108
121
|
end
|
@@ -136,10 +149,8 @@ PRETTY_JSON
|
|
136
149
|
|
137
150
|
it 'hash with array' do
|
138
151
|
json.foo do
|
139
|
-
json
|
140
|
-
|
141
|
-
ary << 2
|
142
|
-
end
|
152
|
+
json << 1
|
153
|
+
json << 2
|
143
154
|
end
|
144
155
|
json.compile!.should == "{\"foo\":[1,2]}"
|
145
156
|
end
|
@@ -153,10 +164,8 @@ PRETTY_JSON
|
|
153
164
|
end
|
154
165
|
|
155
166
|
it 'simple array with object' do
|
156
|
-
json
|
157
|
-
|
158
|
-
ary << (json.foo 'bar')
|
159
|
-
end
|
167
|
+
json << 1
|
168
|
+
json << {:foo => :bar}
|
160
169
|
json.compile!.should == "[1,{\"foo\":\"bar\"}]"
|
161
170
|
end
|
162
171
|
|
@@ -165,10 +174,8 @@ PRETTY_JSON
|
|
165
174
|
json.bar do
|
166
175
|
json.baz 'goo'
|
167
176
|
json.years do
|
168
|
-
json
|
169
|
-
|
170
|
-
ary << 2012
|
171
|
-
end
|
177
|
+
json << 2011
|
178
|
+
json << 2012
|
172
179
|
end
|
173
180
|
end
|
174
181
|
end
|
@@ -203,7 +210,7 @@ PRETTY_JSON
|
|
203
210
|
link_class.new('foo.com', 'parent')
|
204
211
|
]
|
205
212
|
}
|
206
|
-
it 'should work using
|
213
|
+
it 'should work using arrays' do
|
207
214
|
json.result do
|
208
215
|
json.person do
|
209
216
|
json.fname 'George'
|
@@ -216,23 +223,5 @@ PRETTY_JSON
|
|
216
223
|
expected = "{\"result\":{\"person\":{\"fname\":\"George\",\"lname\":\"Burdell\"},\"links\":[{\"href\":\"example.com\",\"rel\":\"self\"},{\"href\":\"foo.com\",\"rel\":\"parent\"}]}}"
|
217
224
|
JSON.parse(json.compile!).should == JSON.parse(expected)
|
218
225
|
end
|
219
|
-
|
220
|
-
it "should work using map! with argument" do
|
221
|
-
json.result do
|
222
|
-
json.person do
|
223
|
-
json.fname 'George'
|
224
|
-
json.lname 'Burdell'
|
225
|
-
end
|
226
|
-
json.links do
|
227
|
-
json.map!(links) do |link|
|
228
|
-
{ :href => link.url, :rel => link.type}
|
229
|
-
end
|
230
|
-
end
|
231
|
-
end
|
232
|
-
expected = "{\"result\":{\"person\":{\"fname\":\"George\",\"lname\":\"Burdell\"},\"links\":[{\"href\":\"example.com\",\"rel\":\"self\"},{\"href\":\"foo.com\",\"rel\":\"parent\"}]}}"
|
233
|
-
JSON.parse(json.compile!).should == JSON.parse(expected)
|
234
|
-
end
|
235
226
|
end
|
236
|
-
|
237
|
-
|
238
227
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: jsonify
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.3
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Bill Siggelkow
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-07-
|
13
|
+
date: 2011-07-27 00:00:00 -04:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -144,7 +144,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
144
144
|
requirements:
|
145
145
|
- - ">="
|
146
146
|
- !ruby/object:Gem::Version
|
147
|
-
hash:
|
147
|
+
hash: 2505547202778738501
|
148
148
|
segments:
|
149
149
|
- 0
|
150
150
|
version: "0"
|
@@ -153,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
153
153
|
requirements:
|
154
154
|
- - ">="
|
155
155
|
- !ruby/object:Gem::Version
|
156
|
-
hash:
|
156
|
+
hash: 2505547202778738501
|
157
157
|
segments:
|
158
158
|
- 0
|
159
159
|
version: "0"
|