oj 2.18.3 → 3.13.14

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 (182) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1324 -0
  3. data/README.md +51 -204
  4. data/RELEASE_NOTES.md +61 -0
  5. data/ext/oj/buf.h +49 -72
  6. data/ext/oj/cache.c +326 -0
  7. data/ext/oj/cache.h +21 -0
  8. data/ext/oj/cache8.c +61 -64
  9. data/ext/oj/cache8.h +12 -39
  10. data/ext/oj/circarray.c +37 -68
  11. data/ext/oj/circarray.h +16 -42
  12. data/ext/oj/code.c +221 -0
  13. data/ext/oj/code.h +40 -0
  14. data/ext/oj/compat.c +231 -107
  15. data/ext/oj/custom.c +1125 -0
  16. data/ext/oj/debug.c +132 -0
  17. data/ext/oj/dump.c +935 -2513
  18. data/ext/oj/dump.h +108 -0
  19. data/ext/oj/dump_compat.c +936 -0
  20. data/ext/oj/dump_leaf.c +164 -0
  21. data/ext/oj/dump_object.c +761 -0
  22. data/ext/oj/dump_strict.c +410 -0
  23. data/ext/oj/encode.h +7 -42
  24. data/ext/oj/encoder.c +43 -0
  25. data/ext/oj/err.c +40 -54
  26. data/ext/oj/err.h +52 -46
  27. data/ext/oj/extconf.rb +21 -30
  28. data/ext/oj/fast.c +1097 -1080
  29. data/ext/oj/intern.c +301 -0
  30. data/ext/oj/intern.h +26 -0
  31. data/ext/oj/mimic_json.c +893 -0
  32. data/ext/oj/object.c +549 -620
  33. data/ext/oj/odd.c +155 -167
  34. data/ext/oj/odd.h +37 -63
  35. data/ext/oj/oj.c +1661 -2063
  36. data/ext/oj/oj.h +341 -270
  37. data/ext/oj/parse.c +974 -737
  38. data/ext/oj/parse.h +105 -97
  39. data/ext/oj/parser.c +1526 -0
  40. data/ext/oj/parser.h +90 -0
  41. data/ext/oj/rails.c +1504 -0
  42. data/ext/oj/rails.h +18 -0
  43. data/ext/oj/reader.c +141 -163
  44. data/ext/oj/reader.h +75 -113
  45. data/ext/oj/resolve.c +45 -93
  46. data/ext/oj/resolve.h +7 -34
  47. data/ext/oj/rxclass.c +143 -0
  48. data/ext/oj/rxclass.h +26 -0
  49. data/ext/oj/saj.c +447 -511
  50. data/ext/oj/saj2.c +348 -0
  51. data/ext/oj/scp.c +91 -138
  52. data/ext/oj/sparse.c +793 -644
  53. data/ext/oj/stream_writer.c +331 -0
  54. data/ext/oj/strict.c +145 -109
  55. data/ext/oj/string_writer.c +493 -0
  56. data/ext/oj/trace.c +72 -0
  57. data/ext/oj/trace.h +28 -0
  58. data/ext/oj/usual.c +1254 -0
  59. data/ext/oj/util.c +136 -0
  60. data/ext/oj/util.h +20 -0
  61. data/ext/oj/val_stack.c +62 -70
  62. data/ext/oj/val_stack.h +95 -129
  63. data/ext/oj/validate.c +51 -0
  64. data/ext/oj/wab.c +622 -0
  65. data/lib/oj/bag.rb +1 -0
  66. data/lib/oj/easy_hash.rb +17 -8
  67. data/lib/oj/error.rb +10 -11
  68. data/lib/oj/json.rb +176 -0
  69. data/lib/oj/mimic.rb +158 -19
  70. data/lib/oj/state.rb +132 -0
  71. data/lib/oj/version.rb +2 -2
  72. data/lib/oj.rb +1 -31
  73. data/pages/Advanced.md +22 -0
  74. data/pages/Compatibility.md +25 -0
  75. data/pages/Custom.md +23 -0
  76. data/pages/Encoding.md +65 -0
  77. data/pages/JsonGem.md +94 -0
  78. data/pages/Modes.md +161 -0
  79. data/pages/Options.md +327 -0
  80. data/pages/Parser.md +309 -0
  81. data/pages/Rails.md +167 -0
  82. data/pages/Security.md +20 -0
  83. data/pages/WAB.md +13 -0
  84. data/test/activerecord/result_test.rb +32 -0
  85. data/test/activesupport4/decoding_test.rb +108 -0
  86. data/test/activesupport4/encoding_test.rb +531 -0
  87. data/test/activesupport4/test_helper.rb +41 -0
  88. data/test/activesupport5/abstract_unit.rb +45 -0
  89. data/test/activesupport5/decoding_test.rb +133 -0
  90. data/test/activesupport5/encoding_test.rb +500 -0
  91. data/test/activesupport5/encoding_test_cases.rb +98 -0
  92. data/test/activesupport5/test_helper.rb +72 -0
  93. data/test/activesupport5/time_zone_test_helpers.rb +39 -0
  94. data/test/activesupport6/abstract_unit.rb +44 -0
  95. data/test/activesupport6/decoding_test.rb +133 -0
  96. data/test/activesupport6/encoding_test.rb +507 -0
  97. data/test/activesupport6/encoding_test_cases.rb +98 -0
  98. data/test/activesupport6/test_common.rb +17 -0
  99. data/test/activesupport6/test_helper.rb +163 -0
  100. data/test/activesupport6/time_zone_test_helpers.rb +39 -0
  101. data/test/activesupport7/abstract_unit.rb +49 -0
  102. data/test/activesupport7/decoding_test.rb +125 -0
  103. data/test/activesupport7/encoding_test.rb +486 -0
  104. data/test/activesupport7/encoding_test_cases.rb +104 -0
  105. data/test/activesupport7/time_zone_test_helpers.rb +47 -0
  106. data/test/bar.rb +9 -0
  107. data/test/baz.rb +16 -0
  108. data/test/bug.rb +11 -46
  109. data/test/foo.rb +69 -16
  110. data/test/helper.rb +10 -1
  111. data/test/isolated/shared.rb +12 -8
  112. data/test/isolated/test_mimic_rails_after.rb +3 -3
  113. data/test/isolated/test_mimic_rails_before.rb +3 -3
  114. data/test/json_gem/json_addition_test.rb +216 -0
  115. data/test/json_gem/json_common_interface_test.rb +153 -0
  116. data/test/json_gem/json_encoding_test.rb +107 -0
  117. data/test/json_gem/json_ext_parser_test.rb +20 -0
  118. data/test/json_gem/json_fixtures_test.rb +35 -0
  119. data/test/json_gem/json_generator_test.rb +397 -0
  120. data/test/json_gem/json_generic_object_test.rb +90 -0
  121. data/test/json_gem/json_parser_test.rb +470 -0
  122. data/test/json_gem/json_string_matching_test.rb +42 -0
  123. data/test/json_gem/test_helper.rb +26 -0
  124. data/test/mem.rb +33 -0
  125. data/test/perf.rb +1 -1
  126. data/test/perf_compat.rb +30 -28
  127. data/test/perf_dump.rb +50 -0
  128. data/test/perf_object.rb +1 -1
  129. data/test/perf_once.rb +58 -0
  130. data/test/perf_parser.rb +189 -0
  131. data/test/perf_scp.rb +11 -10
  132. data/test/perf_strict.rb +30 -19
  133. data/test/perf_wab.rb +131 -0
  134. data/test/prec.rb +23 -0
  135. data/test/sample.rb +0 -1
  136. data/test/sample_json.rb +1 -1
  137. data/test/test_compat.rb +219 -102
  138. data/test/test_custom.rb +533 -0
  139. data/test/test_fast.rb +107 -35
  140. data/test/test_file.rb +19 -25
  141. data/test/test_generate.rb +21 -0
  142. data/test/test_hash.rb +11 -1
  143. data/test/test_integer_range.rb +72 -0
  144. data/test/test_null.rb +376 -0
  145. data/test/test_object.rb +357 -70
  146. data/test/test_parser.rb +27 -0
  147. data/test/test_parser_saj.rb +245 -0
  148. data/test/test_parser_usual.rb +217 -0
  149. data/test/test_rails.rb +35 -0
  150. data/test/test_saj.rb +1 -1
  151. data/test/test_scp.rb +39 -2
  152. data/test/test_strict.rb +186 -7
  153. data/test/test_various.rb +160 -774
  154. data/test/test_wab.rb +307 -0
  155. data/test/test_writer.rb +90 -2
  156. data/test/tests.rb +24 -0
  157. data/test/tests_mimic.rb +14 -0
  158. data/test/tests_mimic_addition.rb +7 -0
  159. data/test/zoo.rb +13 -0
  160. metadata +194 -56
  161. data/ext/oj/hash.c +0 -163
  162. data/ext/oj/hash.h +0 -46
  163. data/ext/oj/hash_test.c +0 -512
  164. data/test/activesupport_datetime_test.rb +0 -23
  165. data/test/bug2.rb +0 -10
  166. data/test/bug3.rb +0 -46
  167. data/test/bug_fast.rb +0 -32
  168. data/test/bug_load.rb +0 -24
  169. data/test/crash.rb +0 -111
  170. data/test/curl/curl_oj.rb +0 -46
  171. data/test/curl/get_oj.rb +0 -24
  172. data/test/curl/just_curl.rb +0 -31
  173. data/test/curl/just_oj.rb +0 -51
  174. data/test/example.rb +0 -11
  175. data/test/io.rb +0 -48
  176. data/test/isolated/test_mimic_rails_datetime.rb +0 -27
  177. data/test/mod.rb +0 -16
  178. data/test/rails.rb +0 -50
  179. data/test/russian.rb +0 -18
  180. data/test/struct.rb +0 -29
  181. data/test/test_serializer.rb +0 -59
  182. data/test/write_timebars.rb +0 -31
data/test/test_object.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
- # encoding: UTF-8
2
+ # encoding: utf-8
3
3
 
4
4
  $: << File.dirname(__FILE__)
5
5
 
@@ -7,11 +7,12 @@ require 'helper'
7
7
 
8
8
  class ObjectJuice < Minitest::Test
9
9
  class Jeez
10
- attr_accessor :x, :y
10
+ attr_accessor :x, :y, :_z
11
11
 
12
12
  def initialize(x, y)
13
13
  @x = x
14
14
  @y = y
15
+ @_z = x.to_s
15
16
  end
16
17
 
17
18
  def eql?(o)
@@ -28,6 +29,49 @@ class ObjectJuice < Minitest::Test
28
29
  end
29
30
  end # Jeez
30
31
 
32
+ class Jam
33
+ attr_accessor :x, :y
34
+
35
+ def initialize(x, y)
36
+ @x = x
37
+ @y = y
38
+ end
39
+
40
+ def eql?(o)
41
+ self.class == o.class && @x == o.x && @y == o.y
42
+ end
43
+ alias == eql?
44
+
45
+ end # Jam
46
+
47
+ class Jazz < Jam
48
+ def initialize(x, y)
49
+ super
50
+ end
51
+ def to_hash()
52
+ { 'json_class' => self.class.to_s, 'x' => @x, 'y' => @y }
53
+ end
54
+ def self.json_create(h)
55
+ self.new(h['x'], h['y'])
56
+ end
57
+ end # Jazz
58
+
59
+ class Orange < Jam
60
+ def initialize(x, y)
61
+ super
62
+ end
63
+
64
+ def as_json()
65
+ { :json_class => self.class,
66
+ :x => @x,
67
+ :y => @y }
68
+ end
69
+
70
+ def self.json_create(h)
71
+ self.new(h['x'], h['y'])
72
+ end
73
+ end
74
+
31
75
  module One
32
76
  module Two
33
77
  module Three
@@ -177,6 +221,13 @@ class ObjectJuice < Minitest::Test
177
221
 
178
222
  def teardown
179
223
  Oj.default_options = @default_options
224
+ #=begin
225
+ if '3.1.0' <= RUBY_VERSION && !(RbConfig::CONFIG['host_os'] =~ /(mingw|mswin)/)
226
+ #Oj::debug_odd("teardown before GC.verify_compaction_references")
227
+ GC.verify_compaction_references(double_heap: true, toward: :empty)
228
+ #Oj::debug_odd("teardown after GC.verify_compaction_references")
229
+ end
230
+ #=end
180
231
  end
181
232
 
182
233
  def test_nil
@@ -208,6 +259,12 @@ class ObjectJuice < Minitest::Test
208
259
  dump_and_load(2.48e16, false)
209
260
  dump_and_load(2.48e100 * 1.0e10, false)
210
261
  dump_and_load(-2.48e100 * 1.0e10, false)
262
+ dump_and_load(1/0.0, false)
263
+ # NaN does not always == NaN
264
+ json = Oj.dump(0/0.0, :mode => :object)
265
+ assert_equal('3.3e14159265358979323846', json)
266
+ loaded = Oj.load(json);
267
+ assert_equal(true, loaded.nan?)
211
268
  end
212
269
 
213
270
  def test_string
@@ -220,6 +277,7 @@ class ObjectJuice < Minitest::Test
220
277
  def test_symbol
221
278
  dump_and_load(:abc, false)
222
279
  dump_and_load(":abc", false)
280
+ dump_and_load(':xyz'.to_sym, false)
223
281
  end
224
282
 
225
283
  def test_encode
@@ -295,15 +353,20 @@ class ObjectJuice < Minitest::Test
295
353
 
296
354
  # BigDecimal
297
355
  def test_bigdecimal_object
298
- dump_and_load(BigDecimal.new('3.14159265358979323846'), false)
356
+ dump_and_load(BigDecimal('3.14159265358979323846'), false)
299
357
  end
300
358
 
301
359
  def test_bigdecimal_load
302
- orig = BigDecimal.new('80.51')
360
+ orig = BigDecimal('80.51')
303
361
  json = Oj.dump(orig, :mode => :object, :bigdecimal_as_decimal => true)
304
362
  bg = Oj.load(json, :mode => :object, :bigdecimal_load => true)
305
363
  assert_equal(BigDecimal, bg.class)
306
364
  assert_equal(orig, bg)
365
+ # Infinity is the same for Float and BigDecimal
366
+ json = Oj.dump(BigDecimal('Infinity'), :mode => :object)
367
+ assert_equal('Infinity', json)
368
+ json = Oj.dump(BigDecimal('-Infinity'), :mode => :object)
369
+ assert_equal('-Infinity', json)
307
370
  end
308
371
 
309
372
  # Stream IO
@@ -345,6 +408,22 @@ class ObjectJuice < Minitest::Test
345
408
  assert_equal({ :x => true, :y => 58, :z => [1, 2, 3]}, obj)
346
409
  end
347
410
 
411
+ def test_class_object
412
+ dump_and_load(ObjectJuice, false)
413
+ end
414
+
415
+ def test_module_object
416
+ dump_and_load(One, false)
417
+ end
418
+
419
+ def test_non_str_hash_object
420
+ json = Oj.dump({ 1 => true, :sim => nil }, :mode => :object)
421
+ h = Oj.load(json, :mode => :strict)
422
+ assert_equal({"^#1" => [1, true], ":sim" => nil}, h)
423
+ h = Oj.load(json, :mode => :object)
424
+ assert_equal({ 1 => true, :sim => nil }, h)
425
+ end
426
+
348
427
  # comments
349
428
  def test_comment_slash
350
429
  json = %{{
@@ -387,11 +466,7 @@ class ObjectJuice < Minitest::Test
387
466
  end
388
467
 
389
468
  def test_xml_time
390
- if RUBY_VERSION.start_with?('1.8')
391
- t = Time.parse('2015-01-05T21:37:07.123456789-08:00')
392
- else
393
- t = Time.new(2015, 1, 5, 21, 37, 7.123456789, -8 * 3600)
394
- end
469
+ t = Time.new(2015, 1, 5, 21, 37, 7.123456789, -8 * 3600)
395
470
  # The fractional seconds are not always recreated exactly which causes a
396
471
  # mismatch so instead the seconds, nsecs, and gmt_offset are checked
397
472
  # separately along with utc.
@@ -409,11 +484,7 @@ class ObjectJuice < Minitest::Test
409
484
  end
410
485
 
411
486
  def test_xml_time_utc
412
- if RUBY_VERSION.start_with?('1.8')
413
- t = Time.parse('2015-01-05T21:37:07.123456789Z')
414
- else
415
- t = Time.utc(2015, 1, 5, 21, 37, 7.123456789)
416
- end
487
+ t = Time.utc(2015, 1, 5, 21, 37, 7.123456789)
417
488
  # The fractional seconds are not always recreated exactly which causes a
418
489
  # mismatch so instead the seconds, nsecs, and gmt_offset are checked
419
490
  # separately along with utc.
@@ -430,11 +501,7 @@ class ObjectJuice < Minitest::Test
430
501
  end
431
502
 
432
503
  def test_ruby_time
433
- if RUBY_VERSION.start_with?('1.8')
434
- t = Time.parse('2015-01-05T21:37:07.123456789-08:00')
435
- else
436
- t = Time.new(2015, 1, 5, 21, 37, 7.123456789, -8 * 3600)
437
- end
504
+ t = Time.new(2015, 1, 5, 21, 37, 7.123456789, -8 * 3600)
438
505
  # The fractional seconds are not always recreated exactly which causes a
439
506
  # mismatch so instead the seconds, nsecs, and gmt_offset are checked
440
507
  # separately along with utc.
@@ -452,11 +519,7 @@ class ObjectJuice < Minitest::Test
452
519
  end
453
520
 
454
521
  def test_ruby_time_12345
455
- if RUBY_VERSION.start_with?('1.8')
456
- t = Time.parse('2015-01-05T21:37:07.123456789+03:25')
457
- else
458
- t = Time.new(2015, 1, 5, 21, 37, 7.123456789, 12345/60*60)
459
- end
522
+ t = Time.new(2015, 1, 5, 21, 37, 7.123456789, 12345/60*60)
460
523
  # The fractional seconds are not always recreated exactly which causes a
461
524
  # mismatch so instead the seconds, nsecs, and gmt_offset are checked
462
525
  # separately along with utc.
@@ -475,11 +538,7 @@ class ObjectJuice < Minitest::Test
475
538
  end
476
539
 
477
540
  def test_ruby_time_utc
478
- if RUBY_VERSION.start_with?('1.8')
479
- t = Time.parse('2015-01-05T21:37:07.123456789Z')
480
- else
481
- t = Time.utc(2015, 1, 5, 21, 37, 7.123456789)
482
- end
541
+ t = Time.utc(2015, 1, 5, 21, 37, 7.123456789)
483
542
  # The fractional seconds are not always recreated exactly which causes a
484
543
  # mismatch so instead the seconds, nsecs, and gmt_offset are checked
485
544
  # separately along with utc.
@@ -497,11 +556,10 @@ class ObjectJuice < Minitest::Test
497
556
  end
498
557
 
499
558
  def test_time_early
500
- if RUBY_VERSION.start_with?('1.8')
501
- t = Time.parse('1954-01-05T21:37:07.123456789-08:00')
502
- else
503
- t = Time.new(1954, 1, 5, 21, 37, 7.123456789, -8 * 3600)
504
- end
559
+ # Windows does not support dates before 1970.
560
+ return if RbConfig::CONFIG['host_os'] =~ /(mingw|mswin)/
561
+
562
+ t = Time.new(1954, 1, 5, 21, 37, 7.123456789, -8 * 3600)
505
563
  # The fractional seconds are not always recreated exactly which causes a
506
564
  # mismatch so instead the seconds, nsecs, and gmt_offset are checked
507
565
  # separately along with utc.
@@ -519,11 +577,7 @@ class ObjectJuice < Minitest::Test
519
577
  end
520
578
 
521
579
  def test_time_unix_zone
522
- if RUBY_VERSION.start_with?('1.8')
523
- t = Time.parse('2015-01-05T21:37:07.123456789-08:00')
524
- else
525
- t = Time.new(2015, 1, 5, 21, 37, 7.123456789, -8 * 3600)
526
- end
580
+ t = Time.new(2015, 1, 5, 21, 37, 7.123456789, -8 * 3600)
527
581
  # The fractional seconds are not always recreated exactly which causes a
528
582
  # mismatch so instead the seconds, nsecs, and gmt_offset are checked
529
583
  # separately along with utc.
@@ -540,32 +594,26 @@ class ObjectJuice < Minitest::Test
540
594
  assert_equal(t.utc_offset, loaded.utc_offset)
541
595
  end
542
596
 
543
- unless RUBY_VERSION.start_with?('1.8')
544
- def test_time_unix_zone_12345
545
- t = Time.new(2015, 1, 5, 21, 37, 7.123456789, 12345)
546
- # The fractional seconds are not always recreated exactly which causes a
547
- # mismatch so instead the seconds, nsecs, and gmt_offset are checked
548
- # separately along with utc.
549
- json = Oj.dump(t, :mode => :object, :time_format => :unix_zone)
550
- #puts json
551
- loaded = Oj.object_load(json);
552
- assert_equal(t.tv_sec, loaded.tv_sec)
553
- if t.respond_to?(:tv_nsec)
554
- assert_equal(t.tv_nsec, loaded.tv_nsec)
555
- else
556
- assert_equal(t.tv_usec, loaded.tv_usec)
557
- end
558
- assert_equal(t.utc?, loaded.utc?)
559
- assert_equal(t.utc_offset, loaded.utc_offset)
597
+ def test_time_unix_zone_12345
598
+ t = Time.new(2015, 1, 5, 21, 37, 7.123456789, 12345)
599
+ # The fractional seconds are not always recreated exactly which causes a
600
+ # mismatch so instead the seconds, nsecs, and gmt_offset are checked
601
+ # separately along with utc.
602
+ json = Oj.dump(t, :mode => :object, :time_format => :unix_zone)
603
+ #puts json
604
+ loaded = Oj.object_load(json);
605
+ assert_equal(t.tv_sec, loaded.tv_sec)
606
+ if t.respond_to?(:tv_nsec)
607
+ assert_equal(t.tv_nsec, loaded.tv_nsec)
608
+ else
609
+ assert_equal(t.tv_usec, loaded.tv_usec)
560
610
  end
611
+ assert_equal(t.utc?, loaded.utc?)
612
+ assert_equal(t.utc_offset, loaded.utc_offset)
561
613
  end
562
614
 
563
615
  def test_time_unix_zone_utc
564
- if RUBY_VERSION.start_with?('1.8')
565
- t = Time.parse('2015-01-05T21:37:07.123456789Z')
566
- else
567
- t = Time.utc(2015, 1, 5, 21, 37, 7.123456789)
568
- end
616
+ t = Time.utc(2015, 1, 5, 21, 37, 7.123456789)
569
617
  # The fractional seconds are not always recreated exactly which causes a
570
618
  # mismatch so instead the seconds, nsecs, and gmt_offset are checked
571
619
  # separately along with utc.
@@ -597,7 +645,7 @@ class ObjectJuice < Minitest::Test
597
645
  begin
598
646
  Oj.object_load(json)
599
647
  rescue Exception => e
600
- assert_equal("Oj::ParseError", e.class().name)
648
+ assert_equal("ArgumentError", e.class().name)
601
649
  return
602
650
  end
603
651
  assert(false, "*** expected an exception")
@@ -645,6 +693,151 @@ class ObjectJuice < Minitest::Test
645
693
  assert_equal({ 1 => true, 'nil' => nil, :sim => 4 }, h)
646
694
  end
647
695
 
696
+ def test_json_object_object
697
+ obj = Jeez.new(true, 58)
698
+ json = Oj.dump(obj, mode: :object, indent: 2, ignore_under: true)
699
+ assert(%{{
700
+ "^o":"ObjectJuice::Jeez",
701
+ "x":true,
702
+ "y":58
703
+ }
704
+ } == json ||
705
+ %{{
706
+ "^o":"ObjectJuice::Jeez",
707
+ "y":58,
708
+ "x":true
709
+ }
710
+ } == json)
711
+ obj2 = Oj.load(json, :mode => :object)
712
+ assert_equal(obj, obj2)
713
+ end
714
+
715
+ def test_to_hash_object_object
716
+ obj = Jazz.new(true, 58)
717
+ json = Oj.dump(obj, :mode => :object, :indent => 2)
718
+ assert(%{{
719
+ "^o":"ObjectJuice::Jazz",
720
+ "x":true,
721
+ "y":58
722
+ }
723
+ } == json ||
724
+ %{{
725
+ "^o":"ObjectJuice::Jazz",
726
+ "y":58,
727
+ "x":true
728
+ }
729
+ } == json)
730
+ obj2 = Oj.load(json, :mode => :object)
731
+ assert_equal(obj, obj2)
732
+ end
733
+
734
+ def test_as_json_object_object
735
+ obj = Orange.new(true, 58)
736
+ json = Oj.dump(obj, :mode => :object, :indent => 2)
737
+ assert(%{{
738
+ "^o":"ObjectJuice::Orange",
739
+ "x":true,
740
+ "y":58
741
+ }
742
+ } == json ||
743
+ %{{
744
+ "^o":"ObjectJuice::Orange",
745
+ "y":58,
746
+ "x":true
747
+ }
748
+ } == json)
749
+ obj2 = Oj.load(json, :mode => :object)
750
+ assert_equal(obj, obj2)
751
+ end
752
+
753
+ def test_object_object_no_cache
754
+ obj = Jam.new(true, 58)
755
+ json = Oj.dump(obj, :mode => :object, :indent => 2)
756
+ assert(%{{
757
+ "^o":"ObjectJuice::Jam",
758
+ "x":true,
759
+ "y":58
760
+ }
761
+ } == json ||
762
+ %{{
763
+ "^o":"ObjectJuice::Jam",
764
+ "y":58,
765
+ "x":true
766
+ }
767
+ } == json)
768
+ obj2 = Oj.load(json, :mode => :object, :class_cache => false)
769
+ assert_equal(obj, obj2)
770
+ end
771
+
772
+ def test_ignore
773
+ obj = Jeez.new(true, 58)
774
+ json = Oj.dump({ 'a' => 7, 'b' => obj }, :mode => :object, :indent => 2, :ignore => [ Jeez ])
775
+ assert_equal(%|{
776
+ "a":7
777
+ }
778
+ |, json)
779
+ end
780
+
781
+ def test_exception
782
+ err = nil
783
+ begin
784
+ raise StandardError.new('A Message')
785
+ rescue Exception => e
786
+ err = e
787
+ end
788
+ json = Oj.dump(err, :mode => :object, :indent => 2)
789
+ #puts "*** #{json}"
790
+ e2 = Oj.load(json, :mode => :strict)
791
+ assert_equal(err.class.to_s, e2['^o'])
792
+ assert_equal(err.message, e2['~mesg'])
793
+ assert_equal(err.backtrace, e2['~bt'])
794
+ e2 = Oj.load(json, :mode => :object)
795
+ if 'rubinius' == $ruby
796
+ assert_equal(e.class, e2.class);
797
+ assert_equal(e.message, e2.message);
798
+ assert_equal(e.backtrace, e2.backtrace);
799
+ else
800
+ assert_equal(e, e2);
801
+ end
802
+ end
803
+
804
+ class SubX < Exception
805
+ def initialize
806
+ super("sub")
807
+ @xyz = 123
808
+ end
809
+ end
810
+
811
+ def test_exception_subclass
812
+ err = nil
813
+ begin
814
+ raise SubX.new
815
+ rescue Exception => e
816
+ err = e
817
+ end
818
+ json = Oj.dump(err, :mode => :object, :indent => 2)
819
+ #puts "*** #{json}"
820
+ e2 = Oj.load(json, :mode => :strict)
821
+ assert_equal(err.class.to_s, e2['^o'])
822
+ assert_equal(err.message, e2['~mesg'])
823
+ assert_equal(err.backtrace, e2['~bt'])
824
+ e2 = Oj.load(json, :mode => :object)
825
+ assert_equal(e, e2);
826
+ end
827
+
828
+ def test_range_object
829
+ Oj.default_options = { :mode => :object }
830
+ json = Oj.dump(1..7, :mode => :object, :indent => 0)
831
+ if 'rubinius' == $ruby
832
+ assert(%{{"^O":"Range","begin":1,"end":7,"exclude_end?":false}} == json)
833
+ else
834
+ assert_equal(%{{"^u":["Range",1,7,false]}}, json)
835
+ end
836
+ dump_and_load(1..7, false)
837
+ dump_and_load(1..1, false)
838
+ dump_and_load(1...7, false)
839
+ end
840
+
648
841
  def test_circular_hash
649
842
  h = { 'a' => 7 }
650
843
  h['b'] = h
@@ -653,6 +846,14 @@ class ObjectJuice < Minitest::Test
653
846
  assert_equal(h2['b'].__id__, h2.__id__)
654
847
  end
655
848
 
849
+
850
+ def test_json_object_missing_fields
851
+ json = %{{ "^u": [ "ObjectJuice::Stuck",1]}}
852
+
853
+ obj = Oj.load(json, mode: :object)
854
+ assert_nil(obj['b'])
855
+ end
856
+
656
857
  def test_circular_array
657
858
  a = [7]
658
859
  a << a
@@ -661,6 +862,38 @@ class ObjectJuice < Minitest::Test
661
862
  assert_equal(a2[1].__id__, a2.__id__)
662
863
  end
663
864
 
865
+ def test_circular_array2
866
+ a = [7]
867
+ a << a
868
+ json = Oj.dump(a, :mode => :object, :indent => 2, :circular => true)
869
+ assert_equal(%{[
870
+ "^i1",
871
+ 7,
872
+ "^r1"
873
+ ]
874
+ }, json)
875
+ a2 = Oj.load(json, :mode => :object, :circular => true)
876
+ assert_equal(a2[1].__id__, a2.__id__)
877
+ end
878
+
879
+ def test_circular_array3
880
+ a = ['^r1']
881
+ json = Oj.dump(a, mode: :object, circular: true)
882
+ assert_equal(%{["^i1","\\u005er1"]}, json)
883
+ a2 = Oj.load(json, mode: :object, circular: true)
884
+ assert_equal(a, a2)
885
+ end
886
+
887
+ def test_circular_hash2
888
+ h = { 'a' => 7 }
889
+ h['b'] = h
890
+ json = Oj.dump(h, :mode => :object, :indent => 2, :circular => true)
891
+ ha = Oj.load(json, :mode => :strict)
892
+ assert_equal({'^i' => 1, 'a' => 7, 'b' => '^r1'}, ha)
893
+ Oj.load(json, :mode => :object, :circular => true)
894
+ assert_equal(h['b'].__id__, h.__id__)
895
+ end
896
+
664
897
  def test_circular_object
665
898
  obj = Jeez.new(nil, 58)
666
899
  obj.x = obj
@@ -669,6 +902,28 @@ class ObjectJuice < Minitest::Test
669
902
  assert_equal(obj2.x.__id__, obj2.__id__)
670
903
  end
671
904
 
905
+ def test_circular_object2
906
+ obj = Jam.new(nil, 58)
907
+ obj.x = obj
908
+ json = Oj.dump(obj, :mode => :object, :indent => 2, :circular => true)
909
+ assert(%{{
910
+ "^o":"ObjectJuice::Jam",
911
+ "^i":1,
912
+ "x":"^r1",
913
+ "y":58
914
+ }
915
+ } == json ||
916
+ %{{
917
+ "^o":"ObjectJuice::Jam",
918
+ "^i":1,
919
+ "y":58,
920
+ "x":"^r1"
921
+ }
922
+ } == json)
923
+ obj2 = Oj.load(json, :mode => :object, :circular => true)
924
+ assert_equal(obj2.x.__id__, obj2.__id__)
925
+ end
926
+
672
927
  def test_circular
673
928
  h = { 'a' => 7 }
674
929
  obj = Jeez.new(h, 58)
@@ -679,8 +934,32 @@ class ObjectJuice < Minitest::Test
679
934
  assert_equal(h['b'].__id__, obj.__id__)
680
935
  end
681
936
 
937
+ def test_circular2
938
+ h = { 'a' => 7 }
939
+ obj = Jam.new(h, 58)
940
+ obj.x['b'] = obj
941
+ json = Oj.dump(obj, :mode => :object, :indent => 2, :circular => true)
942
+ ha = Oj.load(json, :mode => :strict)
943
+ assert_equal({'^o' => 'ObjectJuice::Jam', '^i' => 1, 'x' => { '^i' => 2, 'a' => 7, 'b' => '^r1' }, 'y' => 58 }, ha)
944
+ Oj.load(json, :mode => :object, :circular => true)
945
+ assert_equal(obj.x.__id__, h.__id__)
946
+ assert_equal(h['b'].__id__, obj.__id__)
947
+ end
948
+
949
+ def test_omit_nil
950
+ jam = Jam.new({'a' => 1, 'b' => nil }, nil)
951
+
952
+ json = Oj.dump(jam, :omit_nil => true, :mode => :object)
953
+ assert_equal(%|{"^o":"ObjectJuice::Jam","x":{"a":1}}|, json)
954
+ end
955
+
682
956
  def test_odd_date
683
957
  dump_and_load(Date.new(2012, 6, 19), false)
958
+
959
+ Oj.register_odd(Date, Date, :jd, :jd)
960
+ json = Oj.dump(Date.new(2015, 3, 7), :mode => :object)
961
+ assert_equal(%|{"^O":"Date","jd":2457089}|, json)
962
+ dump_and_load(Date.new(2012, 6, 19), false)
684
963
  end
685
964
 
686
965
  def test_odd_datetime
@@ -688,19 +967,23 @@ class ObjectJuice < Minitest::Test
688
967
  dump_and_load(DateTime.new(2012, 6, 19, 13, 5, Rational(7123456789, 1000000000)), false)
689
968
  end
690
969
 
970
+ def test_bag
971
+ json = %{{
972
+ "^o":"ObjectJuice::Jem",
973
+ "x":true,
974
+ "y":58 }}
975
+ obj = Oj.load(json, :mode => :object, :auto_define => true)
976
+ assert_equal('ObjectJuice::Jem', obj.class.name)
977
+ assert_equal(true, obj.x)
978
+ assert_equal(58, obj.y)
979
+ end
980
+
691
981
  def test_odd_string
692
982
  Oj.register_odd(Strung, Strung, :create, :to_s, 'safe?')
693
983
  s = Strung.new("Pete", true)
694
984
  dump_and_load(s, false)
695
985
  end
696
986
 
697
- def test_odd_date_replaced
698
- Oj.register_odd(Date, Date, :jd, :jd)
699
- json = Oj.dump(Date.new(2015, 3, 7), :mode => :object)
700
- assert_equal(%|{"^O":"Date","jd":2457089}|, json)
701
- dump_and_load(Date.new(2012, 6, 19), false)
702
- end
703
-
704
987
  def test_odd_raw
705
988
  Oj.register_odd_raw(Raw, Raw, :create, :to_json)
706
989
  json = Oj.dump(Raw.new(%|{"a":1}|), :mode => :object)
@@ -738,7 +1021,11 @@ class ObjectJuice < Minitest::Test
738
1021
  json = Oj.dump(obj, :indent => 2, :mode => :object)
739
1022
  puts json if trace
740
1023
  loaded = Oj.object_load(json);
741
- assert_equal(obj, loaded)
1024
+ if obj.nil?
1025
+ assert_nil(loaded)
1026
+ else
1027
+ assert_equal(obj, loaded)
1028
+ end
742
1029
  loaded
743
1030
  end
744
1031
 
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ $: << File.dirname(__FILE__)
5
+ $oj_dir = File.dirname(File.expand_path(File.dirname(__FILE__)))
6
+ %w(lib ext).each do |dir|
7
+ $: << File.join($oj_dir, dir)
8
+ end
9
+
10
+ require 'minitest'
11
+ require 'minitest/autorun'
12
+ require 'stringio'
13
+ require 'date'
14
+ require 'bigdecimal'
15
+ require 'oj'
16
+
17
+ class ParserJuice < Minitest::Test
18
+
19
+ def test_array
20
+ p = Oj::Parser.new(:debug)
21
+ out = p.parse(%|[true, false, null, 123, -1.23, "abc"]|)
22
+ puts out
23
+ out = p.parse(%|{"abc": []}|)
24
+ puts out
25
+ end
26
+
27
+ end