oj 3.9.1 → 3.16.11

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.
Files changed (171) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1452 -0
  3. data/README.md +21 -6
  4. data/RELEASE_NOTES.md +61 -0
  5. data/ext/oj/buf.h +50 -68
  6. data/ext/oj/cache.c +329 -0
  7. data/ext/oj/cache.h +22 -0
  8. data/ext/oj/cache8.c +60 -62
  9. data/ext/oj/cache8.h +9 -36
  10. data/ext/oj/circarray.c +38 -42
  11. data/ext/oj/circarray.h +12 -13
  12. data/ext/oj/code.c +158 -179
  13. data/ext/oj/code.h +20 -22
  14. data/ext/oj/compat.c +145 -205
  15. data/ext/oj/custom.c +740 -880
  16. data/ext/oj/debug.c +126 -0
  17. data/ext/oj/dump.c +1145 -844
  18. data/ext/oj/dump.h +71 -57
  19. data/ext/oj/dump_compat.c +575 -655
  20. data/ext/oj/dump_leaf.c +96 -186
  21. data/ext/oj/dump_object.c +533 -660
  22. data/ext/oj/dump_strict.c +306 -340
  23. data/ext/oj/encode.h +4 -33
  24. data/ext/oj/encoder.c +43 -0
  25. data/ext/oj/err.c +28 -28
  26. data/ext/oj/err.h +39 -42
  27. data/ext/oj/extconf.rb +28 -7
  28. data/ext/oj/fast.c +1052 -1113
  29. data/ext/oj/intern.c +313 -0
  30. data/ext/oj/intern.h +22 -0
  31. data/ext/oj/mem.c +318 -0
  32. data/ext/oj/mem.h +53 -0
  33. data/ext/oj/mimic_json.c +471 -430
  34. data/ext/oj/object.c +532 -580
  35. data/ext/oj/odd.c +156 -142
  36. data/ext/oj/odd.h +25 -26
  37. data/ext/oj/oj.c +1346 -961
  38. data/ext/oj/oj.h +307 -290
  39. data/ext/oj/parse.c +954 -858
  40. data/ext/oj/parse.h +74 -72
  41. data/ext/oj/parser.c +1600 -0
  42. data/ext/oj/parser.h +103 -0
  43. data/ext/oj/rails.c +819 -836
  44. data/ext/oj/rails.h +8 -11
  45. data/ext/oj/reader.c +136 -147
  46. data/ext/oj/reader.h +69 -83
  47. data/ext/oj/resolve.c +41 -63
  48. data/ext/oj/resolve.h +4 -6
  49. data/ext/oj/rxclass.c +69 -72
  50. data/ext/oj/rxclass.h +12 -13
  51. data/ext/oj/saj.c +440 -485
  52. data/ext/oj/saj2.c +584 -0
  53. data/ext/oj/saj2.h +23 -0
  54. data/ext/oj/scp.c +79 -118
  55. data/ext/oj/simd.h +10 -0
  56. data/ext/oj/sparse.c +739 -709
  57. data/ext/oj/stream_writer.c +141 -175
  58. data/ext/oj/strict.c +103 -128
  59. data/ext/oj/string_writer.c +244 -261
  60. data/ext/oj/trace.c +34 -41
  61. data/ext/oj/trace.h +42 -15
  62. data/ext/oj/usual.c +1218 -0
  63. data/ext/oj/usual.h +69 -0
  64. data/ext/oj/util.c +107 -107
  65. data/ext/oj/util.h +4 -3
  66. data/ext/oj/val_stack.c +61 -78
  67. data/ext/oj/val_stack.h +80 -114
  68. data/ext/oj/validate.c +46 -0
  69. data/ext/oj/wab.c +316 -361
  70. data/lib/oj/active_support_helper.rb +1 -3
  71. data/lib/oj/bag.rb +8 -1
  72. data/lib/oj/easy_hash.rb +9 -9
  73. data/lib/oj/error.rb +1 -2
  74. data/lib/oj/json.rb +162 -150
  75. data/lib/oj/mimic.rb +54 -20
  76. data/lib/oj/saj.rb +20 -6
  77. data/lib/oj/schandler.rb +5 -4
  78. data/lib/oj/state.rb +12 -8
  79. data/lib/oj/version.rb +1 -2
  80. data/lib/oj.rb +2 -8
  81. data/pages/Compatibility.md +1 -1
  82. data/pages/Encoding.md +1 -1
  83. data/pages/InstallOptions.md +20 -0
  84. data/pages/JsonGem.md +15 -0
  85. data/pages/Modes.md +9 -3
  86. data/pages/Options.md +62 -12
  87. data/pages/Parser.md +309 -0
  88. data/pages/Rails.md +73 -22
  89. metadata +68 -192
  90. data/ext/oj/hash.c +0 -163
  91. data/ext/oj/hash.h +0 -46
  92. data/ext/oj/hash_test.c +0 -512
  93. data/test/_test_active.rb +0 -76
  94. data/test/_test_active_mimic.rb +0 -96
  95. data/test/_test_mimic_rails.rb +0 -126
  96. data/test/activerecord/result_test.rb +0 -27
  97. data/test/activesupport4/decoding_test.rb +0 -108
  98. data/test/activesupport4/encoding_test.rb +0 -531
  99. data/test/activesupport4/test_helper.rb +0 -41
  100. data/test/activesupport5/decoding_test.rb +0 -125
  101. data/test/activesupport5/encoding_test.rb +0 -485
  102. data/test/activesupport5/encoding_test_cases.rb +0 -90
  103. data/test/activesupport5/test_helper.rb +0 -50
  104. data/test/activesupport5/time_zone_test_helpers.rb +0 -24
  105. data/test/bar.rb +0 -25
  106. data/test/files.rb +0 -29
  107. data/test/foo.rb +0 -21
  108. data/test/helper.rb +0 -26
  109. data/test/isolated/shared.rb +0 -308
  110. data/test/isolated/test_mimic_after.rb +0 -13
  111. data/test/isolated/test_mimic_alone.rb +0 -12
  112. data/test/isolated/test_mimic_as_json.rb +0 -45
  113. data/test/isolated/test_mimic_before.rb +0 -13
  114. data/test/isolated/test_mimic_define.rb +0 -28
  115. data/test/isolated/test_mimic_rails_after.rb +0 -22
  116. data/test/isolated/test_mimic_rails_before.rb +0 -21
  117. data/test/isolated/test_mimic_redefine.rb +0 -15
  118. data/test/json_gem/json_addition_test.rb +0 -216
  119. data/test/json_gem/json_common_interface_test.rb +0 -148
  120. data/test/json_gem/json_encoding_test.rb +0 -107
  121. data/test/json_gem/json_ext_parser_test.rb +0 -20
  122. data/test/json_gem/json_fixtures_test.rb +0 -35
  123. data/test/json_gem/json_generator_test.rb +0 -383
  124. data/test/json_gem/json_generic_object_test.rb +0 -90
  125. data/test/json_gem/json_parser_test.rb +0 -470
  126. data/test/json_gem/json_string_matching_test.rb +0 -42
  127. data/test/json_gem/test_helper.rb +0 -18
  128. data/test/perf.rb +0 -107
  129. data/test/perf_compat.rb +0 -130
  130. data/test/perf_fast.rb +0 -164
  131. data/test/perf_file.rb +0 -64
  132. data/test/perf_object.rb +0 -138
  133. data/test/perf_saj.rb +0 -109
  134. data/test/perf_scp.rb +0 -151
  135. data/test/perf_simple.rb +0 -287
  136. data/test/perf_strict.rb +0 -145
  137. data/test/perf_wab.rb +0 -131
  138. data/test/sample/change.rb +0 -14
  139. data/test/sample/dir.rb +0 -19
  140. data/test/sample/doc.rb +0 -36
  141. data/test/sample/file.rb +0 -48
  142. data/test/sample/group.rb +0 -16
  143. data/test/sample/hasprops.rb +0 -16
  144. data/test/sample/layer.rb +0 -12
  145. data/test/sample/line.rb +0 -20
  146. data/test/sample/oval.rb +0 -10
  147. data/test/sample/rect.rb +0 -10
  148. data/test/sample/shape.rb +0 -35
  149. data/test/sample/text.rb +0 -20
  150. data/test/sample.rb +0 -54
  151. data/test/sample_json.rb +0 -37
  152. data/test/test_compat.rb +0 -509
  153. data/test/test_custom.rb +0 -503
  154. data/test/test_debian.rb +0 -53
  155. data/test/test_fast.rb +0 -470
  156. data/test/test_file.rb +0 -239
  157. data/test/test_gc.rb +0 -49
  158. data/test/test_hash.rb +0 -29
  159. data/test/test_integer_range.rb +0 -73
  160. data/test/test_null.rb +0 -376
  161. data/test/test_object.rb +0 -1018
  162. data/test/test_saj.rb +0 -186
  163. data/test/test_scp.rb +0 -433
  164. data/test/test_strict.rb +0 -410
  165. data/test/test_various.rb +0 -741
  166. data/test/test_wab.rb +0 -307
  167. data/test/test_writer.rb +0 -380
  168. data/test/tests.rb +0 -24
  169. data/test/tests_mimic.rb +0 -14
  170. data/test/tests_mimic_addition.rb +0 -7
  171. data/test/zoo.rb +0 -13
data/test/test_object.rb DELETED
@@ -1,1018 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # encoding: utf-8
3
-
4
- $: << File.dirname(__FILE__)
5
-
6
- require 'helper'
7
-
8
- class ObjectJuice < Minitest::Test
9
- class Jeez
10
- attr_accessor :x, :y
11
-
12
- def initialize(x, y)
13
- @x = x
14
- @y = y
15
- end
16
-
17
- def eql?(o)
18
- self.class == o.class && @x == o.x && @y == o.y
19
- end
20
- alias == eql?
21
-
22
- def to_json(*a)
23
- %{{"json_class":"#{self.class}","x":#{@x},"y":#{@y}}}
24
- end
25
-
26
- def self.json_create(h)
27
- self.new(h['x'], h['y'])
28
- end
29
- end # Jeez
30
-
31
- class Jam
32
- attr_accessor :x, :y
33
-
34
- def initialize(x, y)
35
- @x = x
36
- @y = y
37
- end
38
-
39
- def eql?(o)
40
- self.class == o.class && @x == o.x && @y == o.y
41
- end
42
- alias == eql?
43
-
44
- end # Jam
45
-
46
- class Jazz < Jam
47
- def initialize(x, y)
48
- super
49
- end
50
- def to_hash()
51
- { 'json_class' => self.class.to_s, 'x' => @x, 'y' => @y }
52
- end
53
- def self.json_create(h)
54
- self.new(h['x'], h['y'])
55
- end
56
- end # Jazz
57
-
58
- class Orange < Jam
59
- def initialize(x, y)
60
- super
61
- end
62
-
63
- def as_json()
64
- { :json_class => self.class,
65
- :x => @x,
66
- :y => @y }
67
- end
68
-
69
- def self.json_create(h)
70
- self.new(h['x'], h['y'])
71
- end
72
- end
73
-
74
- module One
75
- module Two
76
- module Three
77
- class Deep
78
-
79
- def initialize()
80
- end
81
-
82
- def eql?(o)
83
- self.class == o.class
84
- end
85
- alias == eql?
86
-
87
- def to_hash()
88
- {'json_class' => "#{self.class.name}"}
89
- end
90
-
91
- def to_json(*a)
92
- %{{"json_class":"#{self.class.name}"}}
93
- end
94
-
95
- def self.json_create(h)
96
- self.new()
97
- end
98
- end # Deep
99
- end # Three
100
- end # Two
101
-
102
- class Stuck2 < Struct.new(:a, :b)
103
- end
104
-
105
- end # One
106
-
107
- class Stuck < Struct.new(:a, :b)
108
- end
109
-
110
- class Strung < String
111
-
112
- def initialize(str, safe)
113
- super(str)
114
- @safe = safe
115
- end
116
-
117
- def safe?()
118
- @safe
119
- end
120
-
121
- def self.create(str, safe)
122
- new(str, safe)
123
- end
124
-
125
- def eql?(o)
126
- super && self.class == o.class && @safe == o.safe?
127
- end
128
- alias == eql?
129
-
130
- def inspect()
131
- return super + '(' + @safe + ')'
132
- end
133
- end
134
-
135
- class AutoStrung < String
136
- attr_accessor :safe
137
-
138
- def initialize(str, safe)
139
- super(str)
140
- @safe = safe
141
- end
142
-
143
- def eql?(o)
144
- self.class == o.class && super(o) && @safe == o.safe
145
- end
146
- alias == eql?
147
- end
148
-
149
- class AutoArray < Array
150
- attr_accessor :safe
151
-
152
- def initialize(a, safe)
153
- super(a)
154
- @safe = safe
155
- end
156
-
157
- def eql?(o)
158
- self.class == o.class && super(o) && @safe == o.safe
159
- end
160
- alias == eql?
161
- end
162
-
163
- class AutoHash < Hash
164
- attr_accessor :safe
165
-
166
- def initialize(h, safe)
167
- super(h)
168
- @safe = safe
169
- end
170
-
171
- def eql?(o)
172
- self.class == o.class && super(o) && @safe == o.safe
173
- end
174
- alias == eql?
175
- end
176
-
177
- class Raw
178
- attr_accessor :json
179
-
180
- def initialize(j)
181
- @json = j
182
- end
183
-
184
- def to_json(*a)
185
- @json
186
- end
187
-
188
- def self.create(h)
189
- h
190
- end
191
- end # Raw
192
-
193
- module Ichi
194
- module Ni
195
- def self.direct(h)
196
- h
197
- end
198
-
199
- module San
200
- class Shi
201
-
202
- attr_accessor :hash
203
-
204
- def initialize(h)
205
- @hash = h
206
- end
207
-
208
- def dump()
209
- @hash
210
- end
211
-
212
- end # Shi
213
- end # San
214
- end # Ni
215
- end # Ichi
216
-
217
- def setup
218
- @default_options = Oj.default_options
219
- end
220
-
221
- def teardown
222
- Oj.default_options = @default_options
223
- end
224
-
225
- def test_nil
226
- dump_and_load(nil, false)
227
- end
228
-
229
- def test_true
230
- dump_and_load(true, false)
231
- end
232
-
233
- def test_false
234
- dump_and_load(false, false)
235
- end
236
-
237
- def test_fixnum
238
- dump_and_load(0, false)
239
- dump_and_load(12345, false)
240
- dump_and_load(-54321, false)
241
- dump_and_load(1, false)
242
- end
243
-
244
- def test_float
245
- dump_and_load(0.0, false)
246
- dump_and_load(12345.6789, false)
247
- dump_and_load(70.35, false)
248
- dump_and_load(-54321.012, false)
249
- dump_and_load(1.7775, false)
250
- dump_and_load(2.5024, false)
251
- dump_and_load(2.48e16, false)
252
- dump_and_load(2.48e100 * 1.0e10, false)
253
- dump_and_load(-2.48e100 * 1.0e10, false)
254
- dump_and_load(1/0.0, false)
255
- # NaN does not always == NaN
256
- json = Oj.dump(0/0.0, :mode => :object)
257
- assert_equal('3.3e14159265358979323846', json)
258
- loaded = Oj.load(json);
259
- assert_equal(true, loaded.nan?)
260
- end
261
-
262
- def test_string
263
- dump_and_load('', false)
264
- dump_and_load('abc', false)
265
- dump_and_load("abc\ndef", false)
266
- dump_and_load("a\u0041", false)
267
- end
268
-
269
- def test_symbol
270
- dump_and_load(:abc, false)
271
- dump_and_load(":abc", false)
272
- dump_and_load(':xyz'.to_sym, false)
273
- end
274
-
275
- def test_encode
276
- opts = Oj.default_options
277
- Oj.default_options = { :ascii_only => false }
278
- dump_and_load("ぴーたー", false)
279
- Oj.default_options = { :ascii_only => true }
280
- json = Oj.dump("ぴーたー")
281
- assert_equal(%{"\\u3074\\u30fc\\u305f\\u30fc"}, json)
282
- dump_and_load("ぴーたー", false)
283
- Oj.default_options = opts
284
- end
285
-
286
- def test_unicode
287
- # hits the 3 normal ranges and one extended surrogate pair
288
- json = %{"\\u019f\\u05e9\\u3074\\ud834\\udd1e"}
289
- obj = Oj.load(json)
290
- json2 = Oj.dump(obj, :ascii_only => true)
291
- assert_equal(json, json2)
292
- end
293
-
294
- def test_array
295
- dump_and_load([], false)
296
- dump_and_load([true, false], false)
297
- dump_and_load(['a', 1, nil], false)
298
- dump_and_load([[nil]], false)
299
- dump_and_load([[nil], 58], false)
300
- end
301
-
302
- def test_array_deep
303
- dump_and_load([1,[2,[3,[4,[5,[6,[7,[8,[9,[10,[11,[12,[13,[14,[15,[16,[17,[18,[19,[20]]]]]]]]]]]]]]]]]]]], false)
304
- end
305
-
306
- # Hash
307
- def test_hash
308
- dump_and_load({}, false)
309
- dump_and_load({ 'true' => true, 'false' => false}, false)
310
- dump_and_load({ 'true' => true, 'array' => [], 'hash' => { }}, false)
311
- end
312
-
313
- def test_hash_deep
314
- dump_and_load({'1' => {
315
- '2' => {
316
- '3' => {
317
- '4' => {
318
- '5' => {
319
- '6' => {
320
- '7' => {
321
- '8' => {
322
- '9' => {
323
- '10' => {
324
- '11' => {
325
- '12' => {
326
- '13' => {
327
- '14' => {
328
- '15' => {
329
- '16' => {
330
- '17' => {
331
- '18' => {
332
- '19' => {
333
- '20' => {}}}}}}}}}}}}}}}}}}}}}, false)
334
- end
335
-
336
- def test_hash_escaped_key
337
- json = %{{"a\nb":true,"c\td":false}}
338
- obj = Oj.object_load(json)
339
- assert_equal({"a\nb" => true, "c\td" => false}, obj)
340
- end
341
-
342
- def test_bignum_object
343
- dump_and_load(7 ** 55, false)
344
- end
345
-
346
- # BigDecimal
347
- def test_bigdecimal_object
348
- dump_and_load(BigDecimal('3.14159265358979323846'), false)
349
- end
350
-
351
- def test_bigdecimal_load
352
- orig = BigDecimal('80.51')
353
- json = Oj.dump(orig, :mode => :object, :bigdecimal_as_decimal => true)
354
- bg = Oj.load(json, :mode => :object, :bigdecimal_load => true)
355
- assert_equal(BigDecimal, bg.class)
356
- assert_equal(orig, bg)
357
- # Infinity is the same for Float and BigDecimal
358
- json = Oj.dump(BigDecimal('Infinity'), :mode => :object)
359
- assert_equal('Infinity', json)
360
- json = Oj.dump(BigDecimal('-Infinity'), :mode => :object)
361
- assert_equal('-Infinity', json)
362
- end
363
-
364
- # Stream IO
365
- def test_io_string
366
- json = %{{
367
- "x":true,
368
- "y":58,
369
- "z": [1,2,3]
370
- }
371
- }
372
- input = StringIO.new(json)
373
- obj = Oj.object_load(input)
374
- assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
375
- end
376
-
377
- def test_io_file
378
- filename = File.join(File.dirname(__FILE__), 'open_file_test.json')
379
- File.open(filename, 'w') { |f| f.write(%{{
380
- "x":true,
381
- "y":58,
382
- "z": [1,2,3]
383
- }
384
- }) }
385
- f = File.new(filename)
386
- obj = Oj.object_load(f)
387
- f.close()
388
- assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
389
- end
390
-
391
- # symbol_keys option
392
- def test_symbol_keys
393
- json = %{{
394
- "x":true,
395
- "y":58,
396
- "z": [1,2,3]
397
- }
398
- }
399
- obj = Oj.object_load(json, :symbol_keys => true)
400
- assert_equal({ :x => true, :y => 58, :z => [1, 2, 3]}, obj)
401
- end
402
-
403
- def test_class_object
404
- dump_and_load(ObjectJuice, false)
405
- end
406
-
407
- def test_module_object
408
- dump_and_load(One, false)
409
- end
410
-
411
- def test_non_str_hash_object
412
- json = Oj.dump({ 1 => true, :sim => nil }, :mode => :object)
413
- h = Oj.load(json, :mode => :strict)
414
- assert_equal({"^#1" => [1, true], ":sim" => nil}, h)
415
- h = Oj.load(json, :mode => :object)
416
- assert_equal({ 1 => true, :sim => nil }, h)
417
- end
418
-
419
- # comments
420
- def test_comment_slash
421
- json = %{{
422
- "x":true,//three
423
- "y":58,
424
- "z": [1,2,
425
- 3 // six
426
- ]}
427
- }
428
- obj = Oj.object_load(json)
429
- assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
430
- end
431
-
432
- def test_comment_c
433
- json = %{{
434
- "x"/*one*/:/*two*/true,
435
- "y":58,
436
- "z": [1,2,3]}
437
- }
438
- obj = Oj.object_load(json)
439
- assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
440
- end
441
-
442
- def test_comment
443
- json = %{{
444
- "x"/*one*/:/*two*/true,//three
445
- "y":58/*four*/,
446
- "z": [1,2/*five*/,
447
- 3 // six
448
- ]
449
- }
450
- }
451
- obj = Oj.object_load(json)
452
- assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
453
- end
454
-
455
- def test_json_module_object
456
- obj = One::Two::Three::Deep.new()
457
- dump_and_load(obj, false)
458
- end
459
-
460
- def test_xml_time
461
- t = Time.new(2015, 1, 5, 21, 37, 7.123456789, -8 * 3600)
462
- # The fractional seconds are not always recreated exactly which causes a
463
- # mismatch so instead the seconds, nsecs, and gmt_offset are checked
464
- # separately along with utc.
465
- json = Oj.dump(t, :mode => :object, :time_format => :xmlschema)
466
- #puts "*** json for test_xml_time '#{json}'"
467
- loaded = Oj.object_load(json);
468
- assert_equal(t.tv_sec, loaded.tv_sec)
469
- if t.respond_to?(:tv_nsec)
470
- assert_equal(t.tv_nsec, loaded.tv_nsec)
471
- else
472
- assert_equal(t.tv_usec, loaded.tv_usec)
473
- end
474
- assert_equal(t.utc?, loaded.utc?)
475
- assert_equal(t.utc_offset, loaded.utc_offset)
476
- end
477
-
478
- def test_xml_time_utc
479
- t = Time.utc(2015, 1, 5, 21, 37, 7.123456789)
480
- # The fractional seconds are not always recreated exactly which causes a
481
- # mismatch so instead the seconds, nsecs, and gmt_offset are checked
482
- # separately along with utc.
483
- json = Oj.dump(t, :mode => :object, :time_format => :xmlschema)
484
- loaded = Oj.object_load(json);
485
- assert_equal(t.tv_sec, loaded.tv_sec)
486
- if t.respond_to?(:tv_nsec)
487
- assert_equal(t.tv_nsec, loaded.tv_nsec)
488
- else
489
- assert_equal(t.tv_usec, loaded.tv_usec)
490
- end
491
- assert_equal(t.utc?, loaded.utc?)
492
- assert_equal(t.utc_offset, loaded.utc_offset)
493
- end
494
-
495
- def test_ruby_time
496
- t = Time.new(2015, 1, 5, 21, 37, 7.123456789, -8 * 3600)
497
- # The fractional seconds are not always recreated exactly which causes a
498
- # mismatch so instead the seconds, nsecs, and gmt_offset are checked
499
- # separately along with utc.
500
- json = Oj.dump(t, :mode => :object, :time_format => :ruby)
501
- #puts "*** json for test_ruby_time '#{json}'"
502
- loaded = Oj.object_load(json);
503
- assert_equal(t.tv_sec, loaded.tv_sec)
504
- if t.respond_to?(:tv_nsec)
505
- assert_equal(t.tv_nsec, loaded.tv_nsec)
506
- else
507
- assert_equal(t.tv_usec, loaded.tv_usec)
508
- end
509
- assert_equal(t.utc?, loaded.utc?)
510
- assert_equal(t.utc_offset, loaded.utc_offset)
511
- end
512
-
513
- def test_ruby_time_12345
514
- t = Time.new(2015, 1, 5, 21, 37, 7.123456789, 12345/60*60)
515
- # The fractional seconds are not always recreated exactly which causes a
516
- # mismatch so instead the seconds, nsecs, and gmt_offset are checked
517
- # separately along with utc.
518
- json = Oj.dump(t, :mode => :object, :time_format => :ruby)
519
- #puts "*** json for test_ruby_time '#{json}'"
520
- loaded = Oj.object_load(json);
521
- #puts "*** loaded: #{loaded}"
522
- assert_equal(t.tv_sec, loaded.tv_sec)
523
- if t.respond_to?(:tv_nsec)
524
- assert_equal(t.tv_nsec, loaded.tv_nsec)
525
- else
526
- assert_equal(t.tv_usec, loaded.tv_usec)
527
- end
528
- assert_equal(t.utc?, loaded.utc?)
529
- assert_equal(t.utc_offset, loaded.utc_offset)
530
- end
531
-
532
- def test_ruby_time_utc
533
- t = Time.utc(2015, 1, 5, 21, 37, 7.123456789)
534
- # The fractional seconds are not always recreated exactly which causes a
535
- # mismatch so instead the seconds, nsecs, and gmt_offset are checked
536
- # separately along with utc.
537
- json = Oj.dump(t, :mode => :object, :time_format => :ruby)
538
- #puts json
539
- loaded = Oj.object_load(json);
540
- assert_equal(t.tv_sec, loaded.tv_sec)
541
- if t.respond_to?(:tv_nsec)
542
- assert_equal(t.tv_nsec, loaded.tv_nsec)
543
- else
544
- assert_equal(t.tv_usec, loaded.tv_usec)
545
- end
546
- assert_equal(t.utc?, loaded.utc?)
547
- assert_equal(t.utc_offset, loaded.utc_offset)
548
- end
549
-
550
- def test_time_early
551
- # Windows does not support dates before 1970.
552
- return if RbConfig::CONFIG['host_os'] =~ /(mingw|mswin)/
553
-
554
- t = Time.new(1954, 1, 5, 21, 37, 7.123456789, -8 * 3600)
555
- # The fractional seconds are not always recreated exactly which causes a
556
- # mismatch so instead the seconds, nsecs, and gmt_offset are checked
557
- # separately along with utc.
558
- json = Oj.dump(t, :mode => :object, :time_format => :unix_zone)
559
- #puts json
560
- loaded = Oj.object_load(json);
561
- assert_equal(t.tv_sec, loaded.tv_sec)
562
- if t.respond_to?(:tv_nsec)
563
- assert_equal(t.tv_nsec, loaded.tv_nsec)
564
- else
565
- assert_equal(t.tv_usec, loaded.tv_usec)
566
- end
567
- assert_equal(t.utc?, loaded.utc?)
568
- assert_equal(t.utc_offset, loaded.utc_offset)
569
- end
570
-
571
- def test_time_unix_zone
572
- t = Time.new(2015, 1, 5, 21, 37, 7.123456789, -8 * 3600)
573
- # The fractional seconds are not always recreated exactly which causes a
574
- # mismatch so instead the seconds, nsecs, and gmt_offset are checked
575
- # separately along with utc.
576
- json = Oj.dump(t, :mode => :object, :time_format => :unix_zone)
577
- #puts json
578
- loaded = Oj.object_load(json);
579
- assert_equal(t.tv_sec, loaded.tv_sec)
580
- if t.respond_to?(:tv_nsec)
581
- assert_equal(t.tv_nsec, loaded.tv_nsec)
582
- else
583
- assert_equal(t.tv_usec, loaded.tv_usec)
584
- end
585
- assert_equal(t.utc?, loaded.utc?)
586
- assert_equal(t.utc_offset, loaded.utc_offset)
587
- end
588
-
589
- def test_time_unix_zone_12345
590
- t = Time.new(2015, 1, 5, 21, 37, 7.123456789, 12345)
591
- # The fractional seconds are not always recreated exactly which causes a
592
- # mismatch so instead the seconds, nsecs, and gmt_offset are checked
593
- # separately along with utc.
594
- json = Oj.dump(t, :mode => :object, :time_format => :unix_zone)
595
- #puts json
596
- loaded = Oj.object_load(json);
597
- assert_equal(t.tv_sec, loaded.tv_sec)
598
- if t.respond_to?(:tv_nsec)
599
- assert_equal(t.tv_nsec, loaded.tv_nsec)
600
- else
601
- assert_equal(t.tv_usec, loaded.tv_usec)
602
- end
603
- assert_equal(t.utc?, loaded.utc?)
604
- assert_equal(t.utc_offset, loaded.utc_offset)
605
- end
606
-
607
- def test_time_unix_zone_utc
608
- t = Time.utc(2015, 1, 5, 21, 37, 7.123456789)
609
- # The fractional seconds are not always recreated exactly which causes a
610
- # mismatch so instead the seconds, nsecs, and gmt_offset are checked
611
- # separately along with utc.
612
- json = Oj.dump(t, :mode => :object, :time_format => :unix_zone)
613
- #puts json
614
- loaded = Oj.object_load(json);
615
- assert_equal(t.tv_sec, loaded.tv_sec)
616
- if t.respond_to?(:tv_nsec)
617
- assert_equal(t.tv_nsec, loaded.tv_nsec)
618
- else
619
- assert_equal(t.tv_usec, loaded.tv_usec)
620
- end
621
- assert_equal(t.utc?, loaded.utc?)
622
- assert_equal(t.utc_offset, loaded.utc_offset)
623
- end
624
-
625
- def test_json_object
626
- obj = Jeez.new(true, 58)
627
- dump_and_load(obj, false)
628
- end
629
-
630
- def test_json_object_create_deep
631
- obj = One::Two::Three::Deep.new()
632
- dump_and_load(obj, false)
633
- end
634
-
635
- def test_json_object_bad
636
- json = %{{"^o":"Junk","x":true}}
637
- begin
638
- Oj.object_load(json)
639
- rescue Exception => e
640
- assert_equal("ArgumentError", e.class().name)
641
- return
642
- end
643
- assert(false, "*** expected an exception")
644
- end
645
-
646
- def test_json_object_not_hat_hash
647
- json = %{{"^#x":[1,2]}}
648
- h = Oj.object_load(json)
649
- assert_equal({1 => 2}, h);
650
-
651
- json = %{{"~#x":[1,2]}}
652
- h = Oj.object_load(json)
653
- assert_equal({'~#x' => [1,2]}, h);
654
- end
655
-
656
- def test_json_struct
657
- obj = Stuck.new(false, 7)
658
- dump_and_load(obj, false)
659
- end
660
-
661
- def test_json_struct2
662
- obj = One::Stuck2.new(false, 7)
663
- dump_and_load(obj, false)
664
- end
665
-
666
- def test_json_anonymous_struct
667
- s = Struct.new(:x, :y)
668
- obj = s.new(1, 2)
669
- json = Oj.dump(obj, :indent => 2, :mode => :object)
670
- #puts json
671
- loaded = Oj.object_load(json);
672
- assert_equal(obj.members, loaded.members)
673
- assert_equal(obj.values, loaded.values)
674
- end
675
-
676
- def test_json_non_str_hash
677
- obj = { 59 => "young", false => true }
678
- dump_and_load(obj, false)
679
- end
680
-
681
- def test_mixed_hash_object
682
- Oj.default_options = { :mode => :object }
683
- json = Oj.dump({ 1 => true, 'nil' => nil, :sim => 4 })
684
- h = Oj.object_load(json)
685
- assert_equal({ 1 => true, 'nil' => nil, :sim => 4 }, h)
686
- end
687
-
688
- def test_json_object_object
689
- obj = Jeez.new(true, 58)
690
- json = Oj.dump(obj, :mode => :object, :indent => 2)
691
- assert(%{{
692
- "^o":"ObjectJuice::Jeez",
693
- "x":true,
694
- "y":58
695
- }
696
- } == json ||
697
- %{{
698
- "^o":"ObjectJuice::Jeez",
699
- "y":58,
700
- "x":true
701
- }
702
- } == json)
703
- obj2 = Oj.load(json, :mode => :object)
704
- assert_equal(obj, obj2)
705
- end
706
-
707
- def test_to_hash_object_object
708
- obj = Jazz.new(true, 58)
709
- json = Oj.dump(obj, :mode => :object, :indent => 2)
710
- assert(%{{
711
- "^o":"ObjectJuice::Jazz",
712
- "x":true,
713
- "y":58
714
- }
715
- } == json ||
716
- %{{
717
- "^o":"ObjectJuice::Jazz",
718
- "y":58,
719
- "x":true
720
- }
721
- } == json)
722
- obj2 = Oj.load(json, :mode => :object)
723
- assert_equal(obj, obj2)
724
- end
725
-
726
- def test_as_json_object_object
727
- obj = Orange.new(true, 58)
728
- json = Oj.dump(obj, :mode => :object, :indent => 2)
729
- assert(%{{
730
- "^o":"ObjectJuice::Orange",
731
- "x":true,
732
- "y":58
733
- }
734
- } == json ||
735
- %{{
736
- "^o":"ObjectJuice::Orange",
737
- "y":58,
738
- "x":true
739
- }
740
- } == json)
741
- obj2 = Oj.load(json, :mode => :object)
742
- assert_equal(obj, obj2)
743
- end
744
-
745
- def test_object_object_no_cache
746
- obj = Jam.new(true, 58)
747
- json = Oj.dump(obj, :mode => :object, :indent => 2)
748
- assert(%{{
749
- "^o":"ObjectJuice::Jam",
750
- "x":true,
751
- "y":58
752
- }
753
- } == json ||
754
- %{{
755
- "^o":"ObjectJuice::Jam",
756
- "y":58,
757
- "x":true
758
- }
759
- } == json)
760
- obj2 = Oj.load(json, :mode => :object, :class_cache => false)
761
- assert_equal(obj, obj2)
762
- end
763
-
764
- def test_ignore
765
- obj = Jeez.new(true, 58)
766
- json = Oj.dump({ 'a' => 7, 'b' => obj }, :mode => :object, :indent => 2, :ignore => [ Jeez ])
767
- assert_equal(%|{
768
- "a":7
769
- }
770
- |, json)
771
- end
772
-
773
- def test_exception
774
- err = nil
775
- begin
776
- raise StandardError.new('A Message')
777
- rescue Exception => e
778
- err = e
779
- end
780
- json = Oj.dump(err, :mode => :object, :indent => 2)
781
- #puts "*** #{json}"
782
- e2 = Oj.load(json, :mode => :strict)
783
- assert_equal(err.class.to_s, e2['^o'])
784
- assert_equal(err.message, e2['~mesg'])
785
- assert_equal(err.backtrace, e2['~bt'])
786
- e2 = Oj.load(json, :mode => :object)
787
- if 'rubinius' == $ruby
788
- assert_equal(e.class, e2.class);
789
- assert_equal(e.message, e2.message);
790
- assert_equal(e.backtrace, e2.backtrace);
791
- else
792
- assert_equal(e, e2);
793
- end
794
- end
795
-
796
- class SubX < Exception
797
- def initialize
798
- super("sub")
799
- @xyz = 123
800
- end
801
- end
802
-
803
- def test_exception_subclass
804
- err = nil
805
- begin
806
- raise SubX.new
807
- rescue Exception => e
808
- err = e
809
- end
810
- json = Oj.dump(err, :mode => :object, :indent => 2)
811
- #puts "*** #{json}"
812
- e2 = Oj.load(json, :mode => :strict)
813
- assert_equal(err.class.to_s, e2['^o'])
814
- assert_equal(err.message, e2['~mesg'])
815
- assert_equal(err.backtrace, e2['~bt'])
816
- e2 = Oj.load(json, :mode => :object)
817
- assert_equal(e, e2);
818
- end
819
-
820
- def test_range_object
821
- Oj.default_options = { :mode => :object }
822
- json = Oj.dump(1..7, :mode => :object, :indent => 0)
823
- if 'rubinius' == $ruby
824
- assert(%{{"^O":"Range","begin":1,"end":7,"exclude_end?":false}} == json)
825
- else
826
- assert_equal(%{{"^u":["Range",1,7,false]}}, json)
827
- end
828
- dump_and_load(1..7, false)
829
- dump_and_load(1..1, false)
830
- dump_and_load(1...7, false)
831
- end
832
-
833
- def test_circular_hash
834
- h = { 'a' => 7 }
835
- h['b'] = h
836
- json = Oj.dump(h, :mode => :object, :indent => 2, :circular => true)
837
- h2 = Oj.object_load(json, :circular => true)
838
- assert_equal(h2['b'].__id__, h2.__id__)
839
- end
840
-
841
-
842
- def test_json_object_missing_fields
843
- json = %{{ "^u": [ "ObjectJuice::Stuck",1]}}
844
-
845
- obj = Oj.load(json, mode: :object)
846
- assert_nil(obj['b'])
847
- end
848
-
849
- def test_circular_array
850
- a = [7]
851
- a << a
852
- json = Oj.dump(a, :mode => :object, :indent => 2, :circular => true)
853
- a2 = Oj.object_load(json, :circular => true)
854
- assert_equal(a2[1].__id__, a2.__id__)
855
- end
856
-
857
- def test_circular_array2
858
- a = [7]
859
- a << a
860
- json = Oj.dump(a, :mode => :object, :indent => 2, :circular => true)
861
- assert_equal(%{[
862
- "^i1",
863
- 7,
864
- "^r1"
865
- ]
866
- }, json)
867
- a2 = Oj.load(json, :mode => :object, :circular => true)
868
- assert_equal(a2[1].__id__, a2.__id__)
869
- end
870
-
871
- def test_circular_hash2
872
- h = { 'a' => 7 }
873
- h['b'] = h
874
- json = Oj.dump(h, :mode => :object, :indent => 2, :circular => true)
875
- ha = Oj.load(json, :mode => :strict)
876
- assert_equal({'^i' => 1, 'a' => 7, 'b' => '^r1'}, ha)
877
- Oj.load(json, :mode => :object, :circular => true)
878
- assert_equal(h['b'].__id__, h.__id__)
879
- end
880
-
881
- def test_circular_object
882
- obj = Jeez.new(nil, 58)
883
- obj.x = obj
884
- json = Oj.dump(obj, :mode => :object, :indent => 2, :circular => true)
885
- obj2 = Oj.object_load(json, :circular => true)
886
- assert_equal(obj2.x.__id__, obj2.__id__)
887
- end
888
-
889
- def test_circular_object2
890
- obj = Jam.new(nil, 58)
891
- obj.x = obj
892
- json = Oj.dump(obj, :mode => :object, :indent => 2, :circular => true)
893
- assert(%{{
894
- "^o":"ObjectJuice::Jam",
895
- "^i":1,
896
- "x":"^r1",
897
- "y":58
898
- }
899
- } == json ||
900
- %{{
901
- "^o":"ObjectJuice::Jam",
902
- "^i":1,
903
- "y":58,
904
- "x":"^r1"
905
- }
906
- } == json)
907
- obj2 = Oj.load(json, :mode => :object, :circular => true)
908
- assert_equal(obj2.x.__id__, obj2.__id__)
909
- end
910
-
911
- def test_circular
912
- h = { 'a' => 7 }
913
- obj = Jeez.new(h, 58)
914
- obj.x['b'] = obj
915
- json = Oj.dump(obj, :mode => :object, :indent => 2, :circular => true)
916
- Oj.object_load(json, :circular => true)
917
- assert_equal(obj.x.__id__, h.__id__)
918
- assert_equal(h['b'].__id__, obj.__id__)
919
- end
920
-
921
- def test_circular2
922
- h = { 'a' => 7 }
923
- obj = Jam.new(h, 58)
924
- obj.x['b'] = obj
925
- json = Oj.dump(obj, :mode => :object, :indent => 2, :circular => true)
926
- ha = Oj.load(json, :mode => :strict)
927
- assert_equal({'^o' => 'ObjectJuice::Jam', '^i' => 1, 'x' => { '^i' => 2, 'a' => 7, 'b' => '^r1' }, 'y' => 58 }, ha)
928
- Oj.load(json, :mode => :object, :circular => true)
929
- assert_equal(obj.x.__id__, h.__id__)
930
- assert_equal(h['b'].__id__, obj.__id__)
931
- end
932
-
933
- def test_omit_nil
934
- jam = Jam.new({'a' => 1, 'b' => nil }, nil)
935
-
936
- json = Oj.dump(jam, :omit_nil => true, :mode => :object)
937
- assert_equal(%|{"^o":"ObjectJuice::Jam","x":{"a":1}}|, json)
938
- end
939
-
940
- def test_odd_date
941
- dump_and_load(Date.new(2012, 6, 19), false)
942
- end
943
-
944
- def test_odd_datetime
945
- dump_and_load(DateTime.new(2012, 6, 19, 13, 5, Rational(4, 3)), false)
946
- dump_and_load(DateTime.new(2012, 6, 19, 13, 5, Rational(7123456789, 1000000000)), false)
947
- end
948
-
949
- def test_bag
950
- json = %{{
951
- "^o":"ObjectJuice::Jem",
952
- "x":true,
953
- "y":58 }}
954
- obj = Oj.load(json, :mode => :object, :auto_define => true)
955
- assert_equal('ObjectJuice::Jem', obj.class.name)
956
- assert_equal(true, obj.x)
957
- assert_equal(58, obj.y)
958
- end
959
-
960
- def test_odd_string
961
- Oj.register_odd(Strung, Strung, :create, :to_s, 'safe?')
962
- s = Strung.new("Pete", true)
963
- dump_and_load(s, false)
964
- end
965
-
966
- def test_odd_date_replaced
967
- Oj.register_odd(Date, Date, :jd, :jd)
968
- json = Oj.dump(Date.new(2015, 3, 7), :mode => :object)
969
- assert_equal(%|{"^O":"Date","jd":2457089}|, json)
970
- dump_and_load(Date.new(2012, 6, 19), false)
971
- end
972
-
973
- def test_odd_raw
974
- Oj.register_odd_raw(Raw, Raw, :create, :to_json)
975
- json = Oj.dump(Raw.new(%|{"a":1}|), :mode => :object)
976
- assert_equal(%|{"^O":"ObjectJuice::Raw","to_json":{"a":1}}|, json)
977
- h = Oj.load(json, :mode => :object)
978
- assert_equal({'a' => 1}, h)
979
- end
980
-
981
- def test_odd_mod
982
- Oj.register_odd(Ichi::Ni, Ichi::Ni, :direct, :dump)
983
- json = Oj.dump(Ichi::Ni::San::Shi.new({'a' => 1}), :mode => :object)
984
- assert_equal(%|{"^O":"ObjectJuice::Ichi::Ni::San::Shi","dump":{"a":1}}|, json)
985
- h = Oj.load(json, :mode => :object)
986
- assert_equal({'a' => 1}, h)
987
- end
988
-
989
- def test_auto_string
990
- s = AutoStrung.new("Pete", true)
991
- dump_and_load(s, false)
992
- end
993
-
994
- def test_auto_array
995
- a = AutoArray.new([1, 'abc', nil], true)
996
- dump_and_load(a, false)
997
- end
998
-
999
- def test_auto_hash
1000
- h = AutoHash.new(nil, true)
1001
- h['a'] = 1
1002
- h['b'] = 2
1003
- dump_and_load(h, false)
1004
- end
1005
-
1006
- def dump_and_load(obj, trace=false)
1007
- json = Oj.dump(obj, :indent => 2, :mode => :object)
1008
- puts json if trace
1009
- loaded = Oj.object_load(json);
1010
- if obj.nil?
1011
- assert_nil(loaded)
1012
- else
1013
- assert_equal(obj, loaded)
1014
- end
1015
- loaded
1016
- end
1017
-
1018
- end