json-endure 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/.rspec ADDED
File without changes
data/LICENSE ADDED
@@ -0,0 +1,14 @@
1
+ This work is licensed under the Creative Commons Attribution 3.0 Unported License.
2
+
3
+ To view a copy of this license, visit :
4
+
5
+ http://creativecommons.org/licenses/by/3.0/
6
+
7
+ Or send a letter to :
8
+
9
+ Creative Commons,
10
+ 444 Castro Street,
11
+ Suite 900,
12
+ Mountain View,
13
+ California, 94041,
14
+ USA.
data/README.md ADDED
@@ -0,0 +1,60 @@
1
+ json-endure
2
+ ===========
3
+
4
+ `json-endure` provides helper methods to the JSON and String classes to
5
+ make-do with truncated JSON text. It does so by closing
6
+ double-quotes, brackets and braces, whether the truncation occurs in
7
+ an array value, hash key, or hash value. These methods may be helpful
8
+ in a case where you want to examine the first bunch of bytes of a very
9
+ large file, without downloading all of it.
10
+
11
+ It will not repair bad JSON encountered before the truncation.
12
+
13
+ License
14
+ -------
15
+
16
+ `json-endure` is licensed under the Creative Commons 3.0 License.
17
+ Details can be found in the file LICENSE.
18
+
19
+ License-file referencing and other doc. formatting taken from
20
+ [damiendallimore](https://github.com/damiendallimore "damiendallimore on GitHub").
21
+
22
+ Install
23
+ -------
24
+
25
+ > gem install json-endure
26
+
27
+ Usage
28
+ -----
29
+
30
+ >> require 'json-endure' #=> true
31
+ >> broken = String.new('{ "123": "90", "abc": { "30') #=> "{ \"123\": \"90\", \"abc\": { \"30"
32
+ >> good_hash = JSON.endure_and_parse broken #=> {"123"=>"90", "abc"=>{"30"=>""}}
33
+ >> fixed = broken.coax_into_json! #=> "{ \"123\": \"90\", \"abc\": { \"30\":\"\"}}"
34
+ >> broken #=> "{ \"123\": \"90\", \"abc\": { \"30\":\"\"}}"
35
+
36
+ Contribute
37
+ ----------
38
+
39
+ Please fork the GitHub project (https://github.com/aburnheimer/json-endure),
40
+ make any changes, commit and push to GitHub, and submit a pull request. Including
41
+ tests for your changes would be greatly appreciated!
42
+
43
+ Resources
44
+ ---------
45
+
46
+ JSON format reference
47
+
48
+ * http://www.json.org/
49
+
50
+ Contact
51
+ -------
52
+
53
+ This project was initiated by Andrew Burnheimer.
54
+
55
+ * Email:
56
+ * aburnheimer@gmail.com
57
+ * Twitter:
58
+ * @aburnheimer
59
+ * Github:
60
+ * https://github.com/aburnheimer/
@@ -0,0 +1,21 @@
1
+ Gem::Specification.new do |s|
2
+ s.platform = Gem::Platform::RUBY
3
+ s.name = 'json-endure'
4
+ s.version = '0.2.2'
5
+ s.summary = %q{Handle truncated JSON-text}
6
+
7
+ s.description = %q{Helper methods to JSON and String to make-do } +
8
+ %q{with truncated JSON text.}
9
+
10
+ s.license = 'CC-BY-3.0'
11
+
12
+ s.author = 'Andrew Burnheimer'
13
+ s.email = 'Andrew_Burnheimer@cable.comcast.com'
14
+ s.homepage = 'https://github.com/aburnheimer/json-endure'
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+
19
+ # specify any dependencies here:
20
+ s.add_dependency("json")
21
+ end
@@ -0,0 +1,2 @@
1
+ require 'json-endure/json'
2
+ require 'json-endure/string'
@@ -0,0 +1,6 @@
1
+ class Array
2
+ def last=(arg)
3
+ self.pop
4
+ self << arg
5
+ end
6
+ end
@@ -0,0 +1,205 @@
1
+ require 'json'
2
+ require File.expand_path File.join(File.dirname(__FILE__), 'array')
3
+
4
+ module JsonStateVariable
5
+ INIT = 10
6
+ IN_ARRAY_PRE_VALUE = 20
7
+ IN_ARRAY_IN_VALUE = 30
8
+ IN_ARRAY_IN_STR_VALUE = 35
9
+ IN_ARRAY_POST_VALUE = 40
10
+ IN_HASH_PRE_KEY = 50
11
+ IN_HASH_IN_KEY = 60
12
+ IN_HASH_POST_KEY = 70
13
+ IN_HASH_PRE_VALUE = 80
14
+ IN_HASH_IN_VALUE = 90
15
+ IN_HASH_IN_STR_VALUE = 95
16
+ IN_HASH_POST_VALUE = 100
17
+ end
18
+
19
+ module JSON
20
+
21
+ module_function
22
+
23
+ def endure_and_parse(str)
24
+ parse endure str
25
+ end
26
+
27
+ def endure(str)
28
+
29
+ literal_mark = literal_char = false
30
+ state_stack = Array.new
31
+
32
+ state_stack << JsonStateVariable::INIT
33
+
34
+ str.chomp!
35
+ arr = str.split(//)
36
+ arr.each do |c|
37
+
38
+ if literal_mark && ! literal_char
39
+ literal_char = true
40
+ elsif literal_mark && literal_char
41
+ literal_mark = false
42
+ literal_char = false
43
+ end
44
+
45
+ case state_stack.last
46
+ when JsonStateVariable::INIT
47
+ if c == '['
48
+ state_stack << JsonStateVariable::IN_ARRAY_PRE_VALUE
49
+ elsif c == '{'
50
+ state_stack << JsonStateVariable::IN_HASH_PRE_KEY
51
+ end
52
+
53
+ when JsonStateVariable::IN_ARRAY_PRE_VALUE
54
+ if c == '['
55
+ state_stack.last = JsonStateVariable::IN_ARRAY_POST_VALUE
56
+ state_stack << JsonStateVariable::IN_ARRAY_PRE_VALUE
57
+ elsif c == '{'
58
+ state_stack.last = JsonStateVariable::IN_ARRAY_POST_VALUE
59
+ state_stack << JsonStateVariable::IN_HASH_PRE_KEY
60
+ elsif c == ','
61
+ state_stack.last = JsonStateVariable::IN_ARRAY_PRE_VALUE
62
+ elsif c == '"'
63
+ state_stack.last = JsonStateVariable::IN_ARRAY_IN_STR_VALUE
64
+ elsif c == ']'
65
+ state_stack.pop
66
+ elsif c =~ /\S/
67
+ state_stack.last = JsonStateVariable::IN_ARRAY_IN_VALUE
68
+ end
69
+
70
+ when JsonStateVariable::IN_ARRAY_IN_VALUE
71
+ if c == ','
72
+ state_stack.last = JsonStateVariable::IN_ARRAY_PRE_VALUE
73
+ elsif c == ']'
74
+ state_stack.pop
75
+ end
76
+
77
+ when JsonStateVariable::IN_ARRAY_IN_STR_VALUE
78
+ if c == '\\'
79
+ literal_mark = true
80
+ break
81
+ elsif c == '"'
82
+ state_stack.last = JsonStateVariable::IN_ARRAY_POST_VALUE
83
+ end
84
+
85
+ when JsonStateVariable::IN_ARRAY_POST_VALUE
86
+ if c == ','
87
+ state_stack.last = JsonStateVariable::IN_ARRAY_PRE_VALUE
88
+ elsif c == ']'
89
+ state_stack.pop
90
+ end
91
+
92
+ when JsonStateVariable::IN_HASH_PRE_KEY
93
+ if c == '"'
94
+ state_stack.last = JsonStateVariable::IN_HASH_IN_KEY
95
+ elsif c == '}'
96
+ state_stack.pop
97
+ end
98
+
99
+ when JsonStateVariable::IN_HASH_IN_KEY
100
+ state_stack.last = JsonStateVariable::IN_HASH_POST_KEY if c == '"'
101
+
102
+ when JsonStateVariable::IN_HASH_POST_KEY
103
+ state_stack.last = JsonStateVariable::IN_HASH_PRE_VALUE if c == ':'
104
+
105
+ when JsonStateVariable::IN_HASH_PRE_VALUE
106
+ if c == '['
107
+ state_stack.last = JsonStateVariable::IN_HASH_POST_VALUE
108
+ state_stack << JsonStateVariable::IN_ARRAY_PRE_VALUE
109
+ elsif c == '{'
110
+ state_stack.last = JsonStateVariable::IN_HASH_POST_VALUE
111
+ state_stack << JsonStateVariable::IN_HASH_PRE_KEY
112
+ elsif c == ','
113
+ state_stack.last = JsonStateVariable::IN_HASH_PRE_KEY
114
+ elsif c == '"'
115
+ state_stack.last = JsonStateVariable::IN_HASH_IN_STR_VALUE
116
+ elsif c =~ /\S/
117
+ state_stack.last = JsonStateVariable::IN_HASH_IN_VALUE
118
+ end
119
+
120
+ when JsonStateVariable::IN_HASH_IN_VALUE
121
+ state_stack.last = JsonStateVariable::IN_HASH_PRE_KEY if c == ','
122
+
123
+ when JsonStateVariable::IN_HASH_IN_STR_VALUE
124
+ if c == '\\'
125
+ literal_mark = true
126
+ break
127
+ elsif c == '"'
128
+ state_stack.last = JsonStateVariable::IN_HASH_POST_VALUE
129
+ end
130
+
131
+ when JsonStateVariable::IN_HASH_POST_VALUE
132
+ if c == ','
133
+ state_stack.last = JsonStateVariable::IN_HASH_PRE_KEY
134
+ elsif c == '}'
135
+ state_stack.pop
136
+ end
137
+
138
+ end unless literal_mark
139
+
140
+ end
141
+
142
+ state_stack.reverse.each do |s|
143
+ catch(:redo) do
144
+ case s
145
+ when JsonStateVariable::INIT
146
+
147
+ when JsonStateVariable::IN_ARRAY_PRE_VALUE
148
+ str << '"'
149
+ s = JsonStateVariable::IN_ARRAY_IN_STR_VALUE
150
+ redo
151
+
152
+ when JsonStateVariable::IN_ARRAY_IN_VALUE
153
+ s = JsonStateVariable::IN_ARRAY_POST_VALUE
154
+ redo
155
+
156
+ when JsonStateVariable::IN_ARRAY_IN_STR_VALUE
157
+ str << '"'
158
+ s = JsonStateVariable::IN_ARRAY_POST_VALUE
159
+ redo
160
+
161
+ when JsonStateVariable::IN_ARRAY_POST_VALUE
162
+ str << ']'
163
+
164
+ when JsonStateVariable::IN_HASH_PRE_KEY
165
+ str << '"'
166
+ s = JsonStateVariable::IN_HASH_IN_KEY
167
+ redo
168
+
169
+ when JsonStateVariable::IN_HASH_IN_KEY
170
+ str << '"'
171
+ s = JsonStateVariable::IN_HASH_POST_KEY
172
+ redo
173
+
174
+ when JsonStateVariable::IN_HASH_POST_KEY
175
+ str << ':'
176
+ s = JsonStateVariable::IN_HASH_PRE_VALUE
177
+ redo
178
+
179
+ when JsonStateVariable::IN_HASH_PRE_VALUE
180
+ str << '"'
181
+ s = JsonStateVariable::IN_HASH_IN_STR_VALUE
182
+ redo
183
+
184
+ when JsonStateVariable::IN_HASH_IN_VALUE
185
+ s = JsonStateVariable::IN_HASH_POST_VALUE
186
+ redo
187
+
188
+ when JsonStateVariable::IN_HASH_IN_STR_VALUE
189
+ str << '"'
190
+ s = JsonStateVariable::IN_HASH_POST_VALUE
191
+ redo
192
+
193
+ when JsonStateVariable::IN_HASH_POST_VALUE
194
+ str << '}'
195
+
196
+ end
197
+ end
198
+ end
199
+
200
+ return str
201
+ end
202
+
203
+ end
204
+
205
+ # vim:set et ts=2 sts=2 sw=2 tw=72 wm=72 ai:
@@ -0,0 +1,17 @@
1
+ require File.expand_path File.join(File.dirname(__FILE__), 'json')
2
+
3
+ class String
4
+
5
+ def coax_into_json()
6
+ str = self.clone
7
+ str.coax_into_json!()
8
+ return str
9
+ end
10
+
11
+ def coax_into_json!()
12
+ self.replace(JSON.endure(self))
13
+ end
14
+
15
+ end
16
+
17
+ # vim:set et ts=2 sts=2 sw=2 tw=72 wm=72 ai:
@@ -0,0 +1,13 @@
1
+ require File.expand_path File.join(File.dirname(__FILE__), '../lib/json-endure/array')
2
+
3
+ describe Array, "#last=" do
4
+ it "sets the last element to a new value" do
5
+ array = Array.new
6
+ array = [ 1, 3, 5 ]
7
+ array.last = 4
8
+ array.last.should eq(4)
9
+ end
10
+ end
11
+
12
+ # vim:set et ts=2 sts=2 sw=2 tw=72 wm=72 ai:
13
+
data/spec/json_spec.rb ADDED
@@ -0,0 +1,376 @@
1
+ $:.delete(File.expand_path File.join(File.dirname(__FILE__), '../lib'))
2
+ require 'json'
3
+ require File.expand_path File.join(File.dirname(__FILE__), '../lib/json-endure/json')
4
+
5
+ describe JSON, "::endure" do
6
+
7
+ it "returns the endured string" do
8
+ string = String.new('{ "123": "90", "abc": { "30')
9
+ expected_value = String.new('{ "123": "90", "abc": { "30":""}}')
10
+
11
+ test_value = JSON.endure(string)
12
+
13
+ test_value.should eq(expected_value)
14
+ end
15
+ end
16
+
17
+ describe JSON, "::endure_and_parse" do
18
+
19
+ it "handles empty arrays" do
20
+ string = String.new('[]')
21
+ expected_value = Array.new
22
+
23
+ test_value = JSON.endure_and_parse(string)
24
+
25
+ test_value.should eq(expected_value)
26
+ end
27
+
28
+ it "handles empty hashes" do
29
+ string = String.new('{}')
30
+ expected_value = Hash.new
31
+
32
+ test_value = JSON.endure_and_parse(string)
33
+
34
+ test_value.should eq(expected_value)
35
+ end
36
+
37
+ # ----- IN_ARRAY -----
38
+
39
+ it "handles an array with a single value" do
40
+ string = String.new('[ 123 ]')
41
+ expected_value = Array.new
42
+ expected_value << 123
43
+
44
+ test_value = JSON.endure_and_parse(string)
45
+
46
+ test_value.should eq(expected_value)
47
+ end
48
+
49
+ it "handles empty hashes inside an array" do
50
+ string = String.new('[1, {}]')
51
+ expected_value = Array.new
52
+ expected_value << 1
53
+ expected_value << Hash.new
54
+
55
+ test_value = JSON.endure_and_parse(string)
56
+
57
+ test_value.should eq(expected_value)
58
+ end
59
+
60
+ it "handles empty arrays inside a hash" do
61
+ string = String.new('{"a": []}')
62
+ expected_value = Hash.new
63
+ expected_value["a"] = Array.new
64
+
65
+ test_value = JSON.endure_and_parse(string)
66
+
67
+ test_value.should eq(expected_value)
68
+ end
69
+
70
+ it "handles interrupted array, pre-value" do
71
+ string = String.new('[ ')
72
+ expected_value = Array.new
73
+ expected_value << ""
74
+
75
+ test_value = JSON.endure_and_parse(string)
76
+
77
+ test_value.should eq(expected_value)
78
+ end
79
+
80
+ it "handles interrupted array mid-value" do
81
+ string = String.new('[ 123, 90')
82
+ expected_value = Array.new
83
+ expected_value << 123
84
+ expected_value << 90
85
+
86
+ test_value = JSON.endure_and_parse(string)
87
+
88
+ test_value.should eq(expected_value)
89
+ end
90
+
91
+ it "handles interrupted array mid-string" do
92
+ string = String.new('[ 123, "90')
93
+ expected_value = Array.new
94
+ expected_value << 123
95
+ expected_value << "90"
96
+
97
+ test_value = JSON.endure_and_parse(string)
98
+
99
+ test_value.should eq(expected_value)
100
+ end
101
+
102
+ it "handles embedded literal \" characters mid-string" do
103
+ string = String.new('[ 123, "9\"0')
104
+ expected_value = Array.new
105
+ expected_value << 123
106
+ expected_value << '9"0'
107
+
108
+ test_value = JSON.endure_and_parse(string)
109
+
110
+ test_value.should eq(expected_value)
111
+ end
112
+
113
+ it "handles an interrupted array inside an array" do
114
+ string = String.new('[ 123, [ 30')
115
+ expected_value = Array.new
116
+ expected_value << 123
117
+ internal_array = Array.new
118
+ internal_array << 30
119
+ expected_value << internal_array
120
+
121
+ test_value = JSON.endure_and_parse(string)
122
+
123
+ test_value.should eq(expected_value)
124
+ end
125
+
126
+ it "handles an interrupted array with a complete internal array" do
127
+ string = String.new('[ 123, [ 30 ]')
128
+ expected_value = Array.new
129
+ expected_value << 123
130
+ internal_array = Array.new
131
+ internal_array << 30
132
+ expected_value << internal_array
133
+
134
+ test_value = JSON.endure_and_parse(string)
135
+
136
+ test_value.should eq(expected_value)
137
+ end
138
+
139
+ it "handles an interrupted array, mid-key, inside an array" do
140
+ string = String.new('[ 123, { "90')
141
+ expected_value = Array.new
142
+ expected_value << 123
143
+ internal_hash = Hash.new
144
+ internal_hash["90"] = ""
145
+ expected_value << internal_hash
146
+
147
+ test_value = JSON.endure_and_parse(string)
148
+
149
+ test_value.should eq(expected_value)
150
+ end
151
+
152
+ it "handles an interrupted array, mid-value, inside an array" do
153
+ string = String.new('[ 123, { "90": 123')
154
+ expected_value = Array.new
155
+ expected_value << 123
156
+ internal_hash = Hash.new
157
+ internal_hash["90"] = 123
158
+ expected_value << internal_hash
159
+
160
+ test_value = JSON.endure_and_parse(string)
161
+
162
+ test_value.should eq(expected_value)
163
+ end
164
+
165
+ it "handles an interrupted array, mid-string, inside an array" do
166
+ string = String.new('[ 123, { "90": "123')
167
+ expected_value = Array.new
168
+ expected_value << 123
169
+ internal_hash = Hash.new
170
+ internal_hash["90"] = "123"
171
+ expected_value << internal_hash
172
+
173
+ test_value = JSON.endure_and_parse(string)
174
+
175
+ test_value.should eq(expected_value)
176
+ end
177
+
178
+ it "handles an interrupted array with a complete internal hash" do
179
+ string = String.new('[ 123, { "90": "123" }' )
180
+ expected_value = Array.new
181
+ expected_value << 123
182
+ internal_hash = Hash.new
183
+ internal_hash["90"] = "123"
184
+ expected_value << internal_hash
185
+
186
+ test_value = JSON.endure_and_parse(string)
187
+
188
+ test_value.should eq(expected_value)
189
+ end
190
+
191
+ it "handles interrupted array after string" do
192
+ string = String.new('[ 123, "90"')
193
+ expected_value = Array.new
194
+ expected_value << 123
195
+ expected_value << "90"
196
+
197
+ test_value = JSON.endure_and_parse(string)
198
+
199
+ test_value.should eq(expected_value)
200
+ end
201
+
202
+ # ----- IN_HASH -----
203
+
204
+ it "handles an array with a single value" do
205
+ string = String.new('{ "123": 90')
206
+ expected_value = Hash.new
207
+ expected_value["123"] = 90
208
+
209
+ test_value = JSON.endure_and_parse(string)
210
+
211
+ test_value.should eq(expected_value)
212
+ end
213
+
214
+ it "handles interrupted hash, pre-key" do
215
+ string = String.new('{ ')
216
+ expected_value = Hash.new
217
+ expected_value[""] = ""
218
+
219
+ test_value = JSON.endure_and_parse(string)
220
+
221
+ test_value.should eq(expected_value)
222
+ end
223
+
224
+ it "handles interrupted hash, mid-key" do
225
+ string = String.new('{ "12')
226
+ expected_value = Hash.new
227
+ expected_value["12"] = ""
228
+
229
+ test_value = JSON.endure_and_parse(string)
230
+
231
+ test_value.should eq(expected_value)
232
+ end
233
+
234
+ it "handles interrupted hash, post-key" do
235
+ string = String.new('{ "12": ')
236
+ expected_value = Hash.new
237
+ expected_value["12"] = ""
238
+
239
+ test_value = JSON.endure_and_parse(string)
240
+
241
+ test_value.should eq(expected_value)
242
+ end
243
+
244
+ it "handles interrupted hash, mid-value" do
245
+ string = String.new('{ "123": 90')
246
+ expected_value = Hash.new
247
+ expected_value["123"] = 90
248
+
249
+ test_value = JSON.endure_and_parse(string)
250
+
251
+ test_value.should eq(expected_value)
252
+ end
253
+
254
+ it "handles interrupted hash, mid-string" do
255
+ string = String.new('{ "123": "90')
256
+ expected_value = Hash.new
257
+ expected_value["123"] = "90"
258
+
259
+ test_value = JSON.endure_and_parse(string)
260
+
261
+ test_value.should eq(expected_value)
262
+ end
263
+
264
+ it "handles embedded literal \" characters mid-string" do
265
+ string = String.new('{ "123": "9\"0')
266
+ expected_value = Hash.new
267
+ expected_value["123"] = '9"0'
268
+
269
+ test_value = JSON.endure_and_parse(string)
270
+
271
+ test_value.should eq(expected_value)
272
+ end
273
+
274
+
275
+ it "handles interrupted hash after string" do
276
+ string = String.new('{ "123": "90"')
277
+ expected_value = Hash.new
278
+ expected_value["123"] = "90"
279
+
280
+ test_value = JSON.endure_and_parse(string)
281
+
282
+ test_value.should eq(expected_value)
283
+ end
284
+
285
+ it "handles an interrupted hash with an interrupted internal array" do
286
+ string = String.new('{ "123": "90", "abc": [ 30')
287
+ expected_value = Hash.new
288
+ expected_value["123"] = "90"
289
+ internal_array = Array.new
290
+ internal_array << 30
291
+ expected_value["abc"] = internal_array
292
+
293
+ test_value = JSON.endure_and_parse(string)
294
+
295
+ test_value.should eq(expected_value)
296
+ end
297
+
298
+ it "handles an interrupted hash with a complete internal array" do
299
+ string = String.new('{ "123": "90", "abc": [ 30 ]')
300
+ expected_value = Hash.new
301
+ expected_value["123"] = "90"
302
+ internal_array = Array.new
303
+ internal_array << 30
304
+ expected_value["abc"] = internal_array
305
+
306
+ test_value = JSON.endure_and_parse(string)
307
+
308
+ test_value.should eq(expected_value)
309
+ end
310
+
311
+ it "handles an interrupted hash, mid-key, inside a hash" do
312
+ string = String.new('{ "123": "90", "abc": { "30')
313
+ expected_value = Hash.new
314
+ expected_value["123"] = "90"
315
+ internal_array = Hash.new
316
+ internal_array["30"] = ""
317
+ expected_value["abc"] = internal_array
318
+
319
+ test_value = JSON.endure_and_parse(string)
320
+
321
+ test_value.should eq(expected_value)
322
+ end
323
+
324
+ it "handles an interrupted hash, mid-value, inside a hash" do
325
+ string = String.new('{ "123": "90", "abc": { "30": 456')
326
+ expected_value = Hash.new
327
+ expected_value["123"] = "90"
328
+ internal_array = Hash.new
329
+ internal_array["30"] = 456
330
+ expected_value["abc"] = internal_array
331
+
332
+ test_value = JSON.endure_and_parse(string)
333
+
334
+ test_value.should eq(expected_value)
335
+ end
336
+
337
+ it "handles an interrupted hash, mid-string, inside a hash" do
338
+ string = String.new('{ "123": "90", "abc": { "30": "456')
339
+ expected_value = Hash.new
340
+ expected_value["123"] = "90"
341
+ internal_array = Hash.new
342
+ internal_array["30"] = "456"
343
+ expected_value["abc"] = internal_array
344
+
345
+ test_value = JSON.endure_and_parse(string)
346
+
347
+ test_value.should eq(expected_value)
348
+ end
349
+
350
+ it "handles an interrupted hash with a complete internal hash" do
351
+ string = String.new('{ "123": "90", "abc": { "30": "456" }')
352
+ expected_value = Hash.new
353
+ expected_value["123"] = "90"
354
+ internal_array = Hash.new
355
+ internal_array["30"] = "456"
356
+ expected_value["abc"] = internal_array
357
+
358
+ test_value = JSON.endure_and_parse(string)
359
+
360
+ test_value.should eq(expected_value)
361
+ end
362
+
363
+ it "handles interrupted hash, after pair, pre-key" do
364
+ string = String.new('{ "123": "90", ')
365
+ expected_value = Hash.new
366
+ expected_value["123"] = "90"
367
+ expected_value[""] = ""
368
+
369
+ test_value = JSON.endure_and_parse(string)
370
+
371
+ test_value.should eq(expected_value)
372
+ end
373
+
374
+ end
375
+
376
+ # vim:set et ts=2 sts=2 sw=2 tw=72 wm=72 ai:
@@ -0,0 +1,27 @@
1
+ require File.expand_path File.join(File.dirname(__FILE__), '../lib/json-endure/string')
2
+
3
+ describe String, "#coax_into_json" do
4
+
5
+ it "returns the string endured string" do
6
+ string = String.new('{ "123": "90", "abc": { "30')
7
+ expected_value = String.new('{ "123": "90", "abc": { "30":""}}')
8
+
9
+ test_value = string.coax_into_json
10
+
11
+ test_value.should eq(expected_value)
12
+ end
13
+ end
14
+
15
+ describe String, "#coax_into_json!" do
16
+
17
+ it "coaxes the string back into proper JSON" do
18
+ string = String.new('{ "123": "90", "abc": { "30')
19
+ expected_value = String.new('{ "123": "90", "abc": { "30":""}}')
20
+
21
+ string.coax_into_json!
22
+
23
+ expected_value.should eq(string)
24
+ end
25
+ end
26
+
27
+ # vim:set et ts=2 sts=2 sw=2 tw=72 wm=72 ai:
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: json-endure
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Andrew Burnheimer
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-11 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: json
16
+ requirement: &2168697580 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2168697580
25
+ description: Helper methods to JSON and String to make-do with truncated JSON text.
26
+ email: Andrew_Burnheimer@cable.comcast.com
27
+ executables: []
28
+ extensions: []
29
+ extra_rdoc_files: []
30
+ files:
31
+ - .rspec
32
+ - LICENSE
33
+ - README.md
34
+ - json-endure.gemspec
35
+ - lib/json-endure.rb
36
+ - lib/json-endure/array.rb
37
+ - lib/json-endure/json.rb
38
+ - lib/json-endure/string.rb
39
+ - spec/array_spec.rb
40
+ - spec/json_spec.rb
41
+ - spec/string_spec.rb
42
+ homepage: https://github.com/aburnheimer/json-endure
43
+ licenses:
44
+ - CC-BY-3.0
45
+ post_install_message:
46
+ rdoc_options: []
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ! '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ requirements: []
62
+ rubyforge_project:
63
+ rubygems_version: 1.8.10
64
+ signing_key:
65
+ specification_version: 3
66
+ summary: Handle truncated JSON-text
67
+ test_files:
68
+ - spec/array_spec.rb
69
+ - spec/json_spec.rb
70
+ - spec/string_spec.rb