oj 3.7.12

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 (156) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +96 -0
  4. data/ext/oj/buf.h +103 -0
  5. data/ext/oj/cache8.c +107 -0
  6. data/ext/oj/cache8.h +48 -0
  7. data/ext/oj/circarray.c +68 -0
  8. data/ext/oj/circarray.h +23 -0
  9. data/ext/oj/code.c +235 -0
  10. data/ext/oj/code.h +42 -0
  11. data/ext/oj/compat.c +299 -0
  12. data/ext/oj/custom.c +1188 -0
  13. data/ext/oj/dump.c +1232 -0
  14. data/ext/oj/dump.h +94 -0
  15. data/ext/oj/dump_compat.c +973 -0
  16. data/ext/oj/dump_leaf.c +252 -0
  17. data/ext/oj/dump_object.c +837 -0
  18. data/ext/oj/dump_strict.c +433 -0
  19. data/ext/oj/encode.h +45 -0
  20. data/ext/oj/err.c +57 -0
  21. data/ext/oj/err.h +70 -0
  22. data/ext/oj/extconf.rb +47 -0
  23. data/ext/oj/fast.c +1771 -0
  24. data/ext/oj/hash.c +163 -0
  25. data/ext/oj/hash.h +46 -0
  26. data/ext/oj/hash_test.c +512 -0
  27. data/ext/oj/mimic_json.c +873 -0
  28. data/ext/oj/object.c +771 -0
  29. data/ext/oj/odd.c +231 -0
  30. data/ext/oj/odd.h +44 -0
  31. data/ext/oj/oj.c +1694 -0
  32. data/ext/oj/oj.h +381 -0
  33. data/ext/oj/parse.c +1085 -0
  34. data/ext/oj/parse.h +111 -0
  35. data/ext/oj/rails.c +1485 -0
  36. data/ext/oj/rails.h +21 -0
  37. data/ext/oj/reader.c +231 -0
  38. data/ext/oj/reader.h +151 -0
  39. data/ext/oj/resolve.c +102 -0
  40. data/ext/oj/resolve.h +14 -0
  41. data/ext/oj/rxclass.c +147 -0
  42. data/ext/oj/rxclass.h +27 -0
  43. data/ext/oj/saj.c +714 -0
  44. data/ext/oj/scp.c +224 -0
  45. data/ext/oj/sparse.c +910 -0
  46. data/ext/oj/stream_writer.c +363 -0
  47. data/ext/oj/strict.c +212 -0
  48. data/ext/oj/string_writer.c +512 -0
  49. data/ext/oj/trace.c +79 -0
  50. data/ext/oj/trace.h +28 -0
  51. data/ext/oj/util.c +136 -0
  52. data/ext/oj/util.h +19 -0
  53. data/ext/oj/val_stack.c +118 -0
  54. data/ext/oj/val_stack.h +185 -0
  55. data/ext/oj/wab.c +631 -0
  56. data/lib/oj.rb +21 -0
  57. data/lib/oj/active_support_helper.rb +41 -0
  58. data/lib/oj/bag.rb +88 -0
  59. data/lib/oj/easy_hash.rb +52 -0
  60. data/lib/oj/error.rb +22 -0
  61. data/lib/oj/json.rb +176 -0
  62. data/lib/oj/mimic.rb +267 -0
  63. data/lib/oj/saj.rb +66 -0
  64. data/lib/oj/schandler.rb +142 -0
  65. data/lib/oj/state.rb +131 -0
  66. data/lib/oj/version.rb +5 -0
  67. data/pages/Advanced.md +22 -0
  68. data/pages/Compatibility.md +25 -0
  69. data/pages/Custom.md +23 -0
  70. data/pages/Encoding.md +65 -0
  71. data/pages/JsonGem.md +79 -0
  72. data/pages/Modes.md +154 -0
  73. data/pages/Options.md +266 -0
  74. data/pages/Rails.md +116 -0
  75. data/pages/Security.md +20 -0
  76. data/pages/WAB.md +13 -0
  77. data/test/_test_active.rb +76 -0
  78. data/test/_test_active_mimic.rb +96 -0
  79. data/test/_test_mimic_rails.rb +126 -0
  80. data/test/activerecord/result_test.rb +27 -0
  81. data/test/activesupport4/decoding_test.rb +108 -0
  82. data/test/activesupport4/encoding_test.rb +531 -0
  83. data/test/activesupport4/test_helper.rb +41 -0
  84. data/test/activesupport5/decoding_test.rb +125 -0
  85. data/test/activesupport5/encoding_test.rb +485 -0
  86. data/test/activesupport5/encoding_test_cases.rb +90 -0
  87. data/test/activesupport5/test_helper.rb +50 -0
  88. data/test/activesupport5/time_zone_test_helpers.rb +24 -0
  89. data/test/big.rb +15 -0
  90. data/test/files.rb +29 -0
  91. data/test/foo.rb +33 -0
  92. data/test/helper.rb +26 -0
  93. data/test/isolated/shared.rb +308 -0
  94. data/test/isolated/test_mimic_after.rb +13 -0
  95. data/test/isolated/test_mimic_alone.rb +12 -0
  96. data/test/isolated/test_mimic_as_json.rb +45 -0
  97. data/test/isolated/test_mimic_before.rb +13 -0
  98. data/test/isolated/test_mimic_define.rb +28 -0
  99. data/test/isolated/test_mimic_rails_after.rb +22 -0
  100. data/test/isolated/test_mimic_rails_before.rb +21 -0
  101. data/test/isolated/test_mimic_redefine.rb +15 -0
  102. data/test/json_gem/json_addition_test.rb +216 -0
  103. data/test/json_gem/json_common_interface_test.rb +148 -0
  104. data/test/json_gem/json_encoding_test.rb +107 -0
  105. data/test/json_gem/json_ext_parser_test.rb +20 -0
  106. data/test/json_gem/json_fixtures_test.rb +35 -0
  107. data/test/json_gem/json_generator_test.rb +383 -0
  108. data/test/json_gem/json_generic_object_test.rb +90 -0
  109. data/test/json_gem/json_parser_test.rb +470 -0
  110. data/test/json_gem/json_string_matching_test.rb +42 -0
  111. data/test/json_gem/test_helper.rb +18 -0
  112. data/test/mem.rb +35 -0
  113. data/test/perf.rb +107 -0
  114. data/test/perf_compat.rb +130 -0
  115. data/test/perf_fast.rb +164 -0
  116. data/test/perf_file.rb +64 -0
  117. data/test/perf_object.rb +138 -0
  118. data/test/perf_saj.rb +109 -0
  119. data/test/perf_scp.rb +151 -0
  120. data/test/perf_simple.rb +287 -0
  121. data/test/perf_strict.rb +145 -0
  122. data/test/perf_wab.rb +131 -0
  123. data/test/sample.rb +54 -0
  124. data/test/sample/change.rb +14 -0
  125. data/test/sample/dir.rb +19 -0
  126. data/test/sample/doc.rb +36 -0
  127. data/test/sample/file.rb +48 -0
  128. data/test/sample/group.rb +16 -0
  129. data/test/sample/hasprops.rb +16 -0
  130. data/test/sample/layer.rb +12 -0
  131. data/test/sample/line.rb +20 -0
  132. data/test/sample/oval.rb +10 -0
  133. data/test/sample/rect.rb +10 -0
  134. data/test/sample/shape.rb +35 -0
  135. data/test/sample/text.rb +20 -0
  136. data/test/sample_json.rb +37 -0
  137. data/test/test_compat.rb +509 -0
  138. data/test/test_custom.rb +406 -0
  139. data/test/test_debian.rb +53 -0
  140. data/test/test_fast.rb +470 -0
  141. data/test/test_file.rb +239 -0
  142. data/test/test_gc.rb +49 -0
  143. data/test/test_hash.rb +29 -0
  144. data/test/test_integer_range.rb +73 -0
  145. data/test/test_null.rb +376 -0
  146. data/test/test_object.rb +1018 -0
  147. data/test/test_saj.rb +186 -0
  148. data/test/test_scp.rb +433 -0
  149. data/test/test_strict.rb +410 -0
  150. data/test/test_various.rb +739 -0
  151. data/test/test_wab.rb +307 -0
  152. data/test/test_writer.rb +380 -0
  153. data/test/tests.rb +24 -0
  154. data/test/tests_mimic.rb +14 -0
  155. data/test/tests_mimic_addition.rb +7 -0
  156. metadata +359 -0
@@ -0,0 +1,90 @@
1
+ require 'bigdecimal'
2
+ require 'date'
3
+ require 'time'
4
+
5
+ module JSONTest
6
+ class Foo
7
+ def initialize(a, b)
8
+ @a, @b = a, b
9
+ end
10
+ end
11
+
12
+ class Hashlike
13
+ def to_hash
14
+ { :foo => "hello", :bar => "world" }
15
+ end
16
+ end
17
+
18
+ class Custom
19
+ def initialize(serialized)
20
+ @serialized = serialized
21
+ end
22
+
23
+ def as_json(options = nil)
24
+ @serialized
25
+ end
26
+ end
27
+
28
+ class MyStruct < Struct.new(:name, :value)
29
+ def initialize(*)
30
+ @unused = "unused instance variable"
31
+ super
32
+ end
33
+ end
34
+
35
+ module EncodingTestCases
36
+ TrueTests = [[ true, %(true) ]]
37
+ FalseTests = [[ false, %(false) ]]
38
+ NilTests = [[ nil, %(null) ]]
39
+ NumericTests = [[ 1, %(1) ],
40
+ [ 2.5, %(2.5) ],
41
+ [ 0.0/0.0, %(null) ],
42
+ [ 1.0/0.0, %(null) ],
43
+ [ -1.0/0.0, %(null) ],
44
+ [ BigDecimal('0.0')/BigDecimal('0.0'), %(null) ],
45
+ [ BigDecimal('2.5'), %("#{BigDecimal('2.5')}") ]]
46
+
47
+ StringTests = [[ 'this is the <string>', %("this is the \\u003cstring\\u003e")],
48
+ [ 'a "string" with quotes & an ampersand', %("a \\"string\\" with quotes \\u0026 an ampersand") ],
49
+ [ 'http://test.host/posts/1', %("http://test.host/posts/1")],
50
+ [ "Control characters: \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\u2028\u2029",
51
+ %("Control characters: \\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\b\\t\\n\\u000b\\f\\r\\u000e\\u000f\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\\u0018\\u0019\\u001a\\u001b\\u001c\\u001d\\u001e\\u001f\\u2028\\u2029") ]]
52
+
53
+ ArrayTests = [[ ['a', 'b', 'c'], %([\"a\",\"b\",\"c\"]) ],
54
+ [ [1, 'a', :b, nil, false], %([1,\"a\",\"b\",null,false]) ]]
55
+
56
+ HashTests = [[ {foo: "bar"}, %({\"foo\":\"bar\"}) ],
57
+ [ {1 => 1, 2 => 'a', 3 => :b, 4 => nil, 5 => false}, %({\"1\":1,\"2\":\"a\",\"3\":\"b\",\"4\":null,\"5\":false}) ]]
58
+
59
+ RangeTests = [[ 1..2, %("1..2")],
60
+ [ 1...2, %("1...2")],
61
+ [ 1.5..2.5, %("1.5..2.5")]]
62
+
63
+ SymbolTests = [[ :a, %("a") ],
64
+ [ :this, %("this") ],
65
+ [ :"a b", %("a b") ]]
66
+
67
+ ObjectTests = [[ Foo.new(1, 2), %({\"a\":1,\"b\":2}) ]]
68
+ HashlikeTests = [[ Hashlike.new, %({\"bar\":\"world\",\"foo\":\"hello\"}) ]]
69
+ StructTests = [[ MyStruct.new(:foo, "bar"), %({\"name\":\"foo\",\"value\":\"bar\"}) ],
70
+ [ MyStruct.new(nil, nil), %({\"name\":null,\"value\":null}) ]]
71
+ CustomTests = [[ Custom.new("custom"), '"custom"' ],
72
+ [ Custom.new(nil), 'null' ],
73
+ [ Custom.new(:a), '"a"' ],
74
+ [ Custom.new([ :foo, "bar" ]), '["foo","bar"]' ],
75
+ [ Custom.new({ :foo => "hello", :bar => "world" }), '{"bar":"world","foo":"hello"}' ],
76
+ [ Custom.new(Hashlike.new), '{"bar":"world","foo":"hello"}' ],
77
+ [ Custom.new(Custom.new(Custom.new(:a))), '"a"' ]]
78
+
79
+ RegexpTests = [[ /^a/, '"(?-mix:^a)"' ], [/^\w{1,2}[a-z]+/ix, '"(?ix-m:^\\\\w{1,2}[a-z]+)"']]
80
+
81
+ DateTests = [[ Date.new(2005,2,1), %("2005/02/01") ]]
82
+ TimeTests = [[ Time.utc(2005,2,1,15,15,10), %("2005/02/01 15:15:10 +0000") ]]
83
+ DateTimeTests = [[ DateTime.civil(2005,2,1,15,15,10), %("2005/02/01 15:15:10 +0000") ]]
84
+
85
+ StandardDateTests = [[ Date.new(2005,2,1), %("2005-02-01") ]]
86
+ StandardTimeTests = [[ Time.utc(2005,2,1,15,15,10), %("2005-02-01T15:15:10.000Z") ]]
87
+ StandardDateTimeTests = [[ DateTime.civil(2005,2,1,15,15,10), %("2005-02-01T15:15:10.000+00:00") ]]
88
+ StandardStringTests = [[ 'this is the <string>', %("this is the <string>")]]
89
+ end
90
+ end
@@ -0,0 +1,50 @@
1
+ require 'active_support/testing/assertions'
2
+ require 'active_support/testing/deprecation'
3
+ require 'active_support/testing/declarative'
4
+ require 'minitest/autorun'
5
+
6
+ module ActiveSupport
7
+ class TestCase < ::Minitest::Test
8
+ # Skips the current run on Rubinius using Minitest::Assertions#skip
9
+ private def rubinius_skip(message = "")
10
+ skip message if RUBY_ENGINE == "rbx"
11
+ end
12
+ # Skips the current run on JRuby using Minitest::Assertions#skip
13
+ private def jruby_skip(message = "")
14
+ skip message if defined?(JRUBY_VERSION)
15
+ end
16
+
17
+ Assertion = Minitest::Assertion
18
+
19
+ alias_method :method_name, :name
20
+
21
+ include ActiveSupport::Testing::Assertions
22
+ include ActiveSupport::Testing::Deprecation
23
+ extend ActiveSupport::Testing::Declarative
24
+
25
+ # test/unit backwards compatibility methods
26
+ alias :assert_raise :assert_raises
27
+ alias :assert_not_empty :refute_empty
28
+ alias :assert_not_equal :refute_equal
29
+ alias :assert_not_in_delta :refute_in_delta
30
+ alias :assert_not_in_epsilon :refute_in_epsilon
31
+ alias :assert_not_includes :refute_includes
32
+ alias :assert_not_instance_of :refute_instance_of
33
+ alias :assert_not_kind_of :refute_kind_of
34
+ alias :assert_no_match :refute_match
35
+ alias :assert_not_nil :refute_nil
36
+ alias :assert_not_operator :refute_operator
37
+ alias :assert_not_predicate :refute_predicate
38
+ alias :assert_not_respond_to :refute_respond_to
39
+ alias :assert_not_same :refute_same
40
+
41
+ # Fails if the block raises an exception.
42
+ #
43
+ # assert_nothing_raised do
44
+ # ...
45
+ # end
46
+ def assert_nothing_raised(*args)
47
+ yield
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,24 @@
1
+ module TimeZoneTestHelpers
2
+ def with_tz_default(tz = nil)
3
+ old_tz = Time.zone
4
+ Time.zone = tz
5
+ yield
6
+ ensure
7
+ Time.zone = old_tz
8
+ end
9
+
10
+ def with_env_tz(new_tz = 'US/Eastern')
11
+ old_tz, ENV['TZ'] = ENV['TZ'], new_tz
12
+ yield
13
+ ensure
14
+ old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ')
15
+ end
16
+
17
+ def with_preserve_timezone(value)
18
+ old_preserve_tz = ActiveSupport.to_time_preserves_timezone
19
+ ActiveSupport.to_time_preserves_timezone = value
20
+ yield
21
+ ensure
22
+ ActiveSupport.to_time_preserves_timezone = old_preserve_tz
23
+ end
24
+ end
@@ -0,0 +1,15 @@
1
+ #require 'active_support'
2
+ #require 'active_support/core_ext'
3
+ #require 'active_support/json'
4
+ require 'oj'
5
+
6
+ #Oj.optimize_rails
7
+ Oj.mimic_JSON
8
+
9
+ h = {:type=>:record, :name=>:group, :namespace=>"com.salsify.identity", :fields=>[{:name=>"id", :type=>{:name=>:salsify_uuid, :type=>:fixed, :namespace=>"com.salsify", :size=>38}}, {:name=>"type", :type=>"string", :default=>"groups"}, {:name=>"external_id", :type=>[:null, "string"], :default=>nil}, {:name=>"created_at", :type=>{:type=>"long", :logicalType=>"timestamp-micros"}}, {:name=>"updated_at", :type=>{:type=>"long", :logicalType=>"timestamp-micros"}}, {:name=>"name", :type=>"string"}, {:name=>"policy", :type=>[:null, {:type=>:record, :name=>:policy, :namespace=>"com.salsify.security", :fields=>[{:name=>"created_at", :type=>{:type=>"long", :logicalType=>"timestamp-micros"}}, {:name=>"updated_at", :type=>{:type=>"long", :logicalType=>"timestamp-micros"}}, {:name=>"id", :type=>"com.salsify.salsify_uuid"}, {:name=>"type", :type=>"string", :default=>"policies"}, {:name=>"external_id", :type=>[:null, "string"], :default=>nil}, {:name=>"name", :type=>"string"}, {:name=>"statements", :type=>{:type=>:array, :items=>{:type=>:record, :name=>:statement, :namespace=>"com.salsify.security", :fields=>[{:name=>"created_at", :type=>{:type=>"long", :logicalType=>"timestamp-micros"}}, {:name=>"updated_at", :type=>{:type=>"long", :logicalType=>"timestamp-micros"}}, {:name=>"id", :type=>"com.salsify.salsify_uuid"}, {:name=>"type", :type=>"string", :default=>"statements"}, {:name=>"external_id", :type=>[:null, "string"], :default=>nil}, {:name=>"action", :type=>{:name=>"__statement_action_enum", :type=>:enum, :namespace=>"com.salsify.security", :symbols=>[:manage, :read]}}, {:name=>"resource", :type=>{:name=>"__statement_resource_enum", :type=>:enum, :namespace=>"com.salsify.security", :symbols=>[:product, :digital_asset]}}, {:name=>"conditions", :type=>{:type=>:array, :items=>{:type=>:record, :name=>:condition, :namespace=>"com.salsify.security", :fields=>[{:name=>"created_at", :type=>{:type=>"long", :logicalType=>"timestamp-micros"}}, {:name=>"updated_at", :type=>{:type=>"long", :logicalType=>"timestamp-micros"}}, {:name=>"id", :type=>"com.salsify.salsify_uuid"}, {:name=>"type", :type=>"string", :default=>"conditions"}, {:name=>"external_id", :type=>[:null, "string"], :default=>nil}, {:name=>"operator", :type=>{:name=>"__condition_operator_enum", :type=>:enum, :namespace=>"com.salsify.security", :symbols=>[:equals]}}, {:name=>"attribute_type", :type=>{:name=>"__condition_attribute_type_enum", :type=>:enum, :namespace=>"com.salsify.security", :symbols=>[:resource]}}, {:name=>"value", :type=>"string"}, {:name=>"attribute", :type=>[:null, {:type=>:record, :name=>:reference, :namespace=>"com.salsify", :fields=>[{:name=>"id", :type=>"com.salsify.salsify_uuid"}, {:name=>"type", :type=>"string", :doc=>"snake_case, plural name for the resource type"}, {:name=>"external_id", :type=>[:null, "string"], :default=>nil}]}], :default=>nil}, {:name=>"broken", :type=>[:null, "boolean"], :default=>nil}]}}}]}}}]}], :default=>nil}]}
10
+
11
+ #Oj.dump(h)
12
+ puts JSON.pretty_generate(h)
13
+ #puts JSON.fast_generate(h)
14
+ #puts JSON.generate(h)
15
+
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby -wW2
2
+
3
+ if $0 == __FILE__
4
+ $: << '.'
5
+ $: << '..'
6
+ $: << '../lib'
7
+ $: << '../ext'
8
+ end
9
+
10
+ require 'pp'
11
+ require 'sample/file'
12
+ require 'sample/dir'
13
+
14
+ def files(dir)
15
+ d = ::Sample::Dir.new(dir)
16
+ Dir.new(dir).each do |fn|
17
+ next if fn.start_with?('.')
18
+ filename = File.join(dir, fn)
19
+ #filename = '.' == dir ? fn : File.join(dir, fn)
20
+ if File.directory?(filename)
21
+ d << files(filename)
22
+ else
23
+ d << ::Sample::File.new(filename)
24
+ end
25
+ end
26
+ #pp d
27
+ d
28
+ end
29
+
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $: << '.'
4
+ $: << '../lib'
5
+ $: << '../ext'
6
+
7
+ require 'oj'
8
+
9
+ f = File.open("foo.json", "w")
10
+ 100_000.times do
11
+ obj = { created_at: DateTime.new(2001,2,3,4,5,6) }
12
+ Oj.to_stream(f, obj)
13
+ f.puts
14
+ f.flush
15
+ end
16
+ f.close
17
+
18
+ def run_test_thread
19
+ threads = Array.new(3) do
20
+ Thread.new do
21
+ counter = 0
22
+ File.open("foo.json", "r") { |f| Oj.enum_for(:load, f).lazy.each { counter += 1 } }
23
+ #File.open("odd_file.jsonl", "r") { |f| Oj.enum_for(:load, f).lazy.each { counter += 1 } }
24
+ puts counter
25
+ end
26
+ end
27
+ threads.each(&:join)
28
+ end
29
+
30
+ 100.times do |i|
31
+ puts i
32
+ run_test_thread
33
+ end
@@ -0,0 +1,26 @@
1
+ # Ubuntu does not accept arguments to ruby when called using env. To get warnings to show up the -w options is
2
+ # required. That can be set in the RUBYOPT environment variable.
3
+ # export RUBYOPT=-w
4
+
5
+ $VERBOSE = true
6
+
7
+ %w(lib ext test).each do |dir|
8
+ $LOAD_PATH.unshift File.expand_path("../../#{dir}", __FILE__)
9
+ end
10
+
11
+ require 'minitest'
12
+ require 'minitest/autorun'
13
+ require 'stringio'
14
+ require 'date'
15
+ require 'bigdecimal'
16
+ require 'pp'
17
+ require 'oj'
18
+
19
+ $ruby = RUBY_DESCRIPTION.split(' ')[0]
20
+ $ruby = 'ree' if 'ruby' == $ruby && RUBY_DESCRIPTION.include?('Ruby Enterprise Edition')
21
+
22
+ class Range
23
+ def to_hash()
24
+ { 'begin' => self.begin, 'end' => self.end, 'exclude_end' => self.exclude_end? }
25
+ end
26
+ end
@@ -0,0 +1,308 @@
1
+ # encoding: UTF-8
2
+
3
+ # The rails tests set this to true. Both Rails and the JSON gem monkey patch the
4
+ # as_json methods on several base classes. Depending on which one replaces the
5
+ # method last the behavior will be different. Oj.mimic_JSON abides by the same
6
+ # conflicting behavior and the tests reflect that.
7
+ $rails_monkey = false unless defined?($rails_monkey)
8
+
9
+ class SharedMimicTest < Minitest::Test
10
+ class Jam
11
+ attr_accessor :x, :y
12
+
13
+ def initialize(x, y)
14
+ @x = x
15
+ @y = y
16
+ end
17
+
18
+ def eql?(o)
19
+ self.class == o.class && @x == o.x && @y == o.y
20
+ end
21
+ alias == eql?
22
+
23
+ def as_json()
24
+ {"json_class" => self.class.to_s,"x" => @x,"y" => @y}
25
+ end
26
+
27
+ def self.json_create(h)
28
+ self.new(h['x'], h['y'])
29
+ end
30
+
31
+ end # Jam
32
+
33
+ def setup
34
+ @default_options = Oj.default_options
35
+ @time = Time.at(1400000000).utc
36
+ @expected_time_string =
37
+ if defined?(Rails)
38
+ %{"2014-05-13T16:53:20.000Z"}
39
+ else
40
+ %{"2014-05-13 16:53:20 UTC"}
41
+ end
42
+ end
43
+
44
+ def teardown
45
+ Oj.default_options = @default_options
46
+ end
47
+
48
+ # exception
49
+ def test_exception
50
+ begin
51
+ JSON.parse("{")
52
+ puts "Failed"
53
+ rescue JSON::ParserError
54
+ assert(true)
55
+ rescue Exception
56
+ assert(false, 'Expected a JSON::ParserError')
57
+ end
58
+ end
59
+
60
+ # dump
61
+ def test_dump_string
62
+ json = JSON.dump([1, true, nil, @time])
63
+ if $rails_monkey
64
+ assert_equal(%{[1,true,null,#{@expected_time_string}]}, json)
65
+ else
66
+ assert_equal(%{[1,true,null,{"json_class":"Time","s":1400000000,"n":0}]}, json)
67
+ end
68
+ end
69
+
70
+ def test_dump_with_options
71
+ Oj.default_options= {:indent => 2} # JSON this will not change anything
72
+ json = JSON.dump([1, true, nil, @time])
73
+ if $rails_monkey
74
+ assert_equal(%{[
75
+ 1,
76
+ true,
77
+ null,
78
+ #{@expected_time_string}
79
+ ]
80
+ }, json)
81
+ else
82
+ assert_equal(%{[
83
+ 1,
84
+ true,
85
+ null,
86
+ {
87
+ "json_class":"Time",
88
+ "s":1400000000,
89
+ "n\":0
90
+ }
91
+ ]
92
+ }, json)
93
+ end
94
+ end
95
+
96
+ def test_dump_io
97
+ s = StringIO.new()
98
+ json = JSON.dump([1, true, nil, @time], s)
99
+ assert_equal(s, json)
100
+ if $rails_monkey
101
+ assert_equal(%{[1,true,null,#{@expected_time_string}]}, s.string)
102
+ else
103
+ assert_equal(%{[1,true,null,{"json_class":"Time","s":1400000000,"n":0}]}, s.string)
104
+ end
105
+ end
106
+ # TBD options
107
+
108
+ def test_dump_struct
109
+ # anonymous Struct not supported by json so name it
110
+ if Object.const_defined?("Struct::Abc")
111
+ s = Struct::Abc
112
+ else
113
+ s = Struct.new("Abc", :a, :b, :c)
114
+ end
115
+ o = s.new(1, 'two', [true, false])
116
+ json = JSON.dump(o)
117
+ if o.respond_to?(:as_json)
118
+ if $rails_monkey
119
+ assert_equal(%|{"a":1,"b":"two","c":[true,false]}|, json)
120
+ else
121
+ assert_equal(%|{"json_class":"Struct::Abc","v":[1,"two",[true,false]]}|, json)
122
+ end
123
+ else
124
+ j = '"' + o.to_s.gsub('"', '\\"') + '"'
125
+ assert_equal(j, json)
126
+ end
127
+ end
128
+
129
+ # load
130
+ def test_load_string
131
+ json = %{{"a":1,"b":[true,false]}}
132
+ obj = JSON.load(json)
133
+ assert_equal({ 'a' => 1, 'b' => [true, false]}, obj)
134
+ end
135
+
136
+ def test_load_io
137
+ json = %{{"a":1,"b":[true,false]}}
138
+ obj = JSON.load(StringIO.new(json))
139
+ assert_equal({ 'a' => 1, 'b' => [true, false]}, obj)
140
+ end
141
+
142
+ def test_load_proc
143
+ Oj.mimic_JSON
144
+ children = []
145
+ json = %{{"a":1,"b":[true,false]}}
146
+ if 'rubinius' == $ruby
147
+ obj = JSON.load(json) {|x| children << x }
148
+ else
149
+ p = Proc.new {|x| children << x }
150
+ obj = JSON.load(json, p)
151
+ end
152
+ assert_equal({ 'a' => 1, 'b' => [true, false]}, obj)
153
+ assert([1, true, false, [true, false], { 'a' => 1, 'b' => [true, false]}] == children ||
154
+ [true, false, [true, false], 1, { 'a' => 1, 'b' => [true, false]}] == children,
155
+ "children don't match")
156
+ end
157
+
158
+ def test_parse_with_quirks_mode
159
+ json = %{null}
160
+ assert_equal(nil, JSON.parse(json, :quirks_mode => true))
161
+ assert_raises(JSON::ParserError) { JSON.parse(json, :quirks_mode => false) }
162
+ assert_raises(JSON::ParserError) { JSON.parse(json) }
163
+ end
164
+
165
+ def test_parse_with_empty_string
166
+ Oj.mimic_JSON
167
+ assert_raises(JSON::ParserError) { JSON.parse(' ') }
168
+ assert_raises(JSON::ParserError) { JSON.parse("\t\t\n ") }
169
+ end
170
+
171
+ # []
172
+ def test_bracket_load
173
+ json = %{{"a":1,"b":[true,false]}}
174
+ obj = JSON[json]
175
+ assert_equal({ 'a' => 1, 'b' => [true, false]}, obj)
176
+ end
177
+
178
+ def test_bracket_dump
179
+ json = JSON[[1, true, nil]]
180
+ assert_equal(%{[1,true,null]}, json)
181
+ end
182
+
183
+ # generate
184
+ def test_generate
185
+ json = JSON.generate({ 'a' => 1, 'b' => [true, false]})
186
+ assert(%{{"a":1,"b":[true,false]}} == json ||
187
+ %{{"b":[true,false],"a":1}} == json)
188
+ end
189
+ def test_generate_options
190
+ json = JSON.generate({ 'a' => 1, 'b' => [true, false]},
191
+ :indent => "--",
192
+ :array_nl => "\n",
193
+ :object_nl => "#\n",
194
+ :space => "*",
195
+ :space_before => "~")
196
+ assert(%{{#
197
+ --"a"~:*1,#
198
+ --"b"~:*[
199
+ ----true,
200
+ ----false
201
+ --]#
202
+ }} == json ||
203
+ %{{#
204
+ --"b"~:*[
205
+ ----true,
206
+ ----false
207
+ --],#
208
+ --"a"~:*1#
209
+ }} == json)
210
+
211
+ end
212
+
213
+ # fast_generate
214
+ def test_fast_generate
215
+ json = JSON.generate({ 'a' => 1, 'b' => [true, false]})
216
+ assert(%{{"a":1,"b":[true,false]}} == json ||
217
+ %{{"b":[true,false],"a":1}} == json)
218
+ end
219
+
220
+ # pretty_generate
221
+ def test_pretty_generate
222
+ json = JSON.pretty_generate({ 'a' => 1, 'b' => [true, false]})
223
+ assert(%{{
224
+ "a": 1,
225
+ "b": [
226
+ true,
227
+ false
228
+ ]
229
+ }} == json ||
230
+ %{{
231
+ "b": [
232
+ true,
233
+ false
234
+ ],
235
+ "a": 1
236
+ }} == json)
237
+ end
238
+
239
+ # parse
240
+ def test_parse
241
+ json = %{{"a":1,"b":[true,false]}}
242
+ obj = JSON.parse(json)
243
+ assert_equal({ 'a' => 1, 'b' => [true, false]}, obj)
244
+ end
245
+ def test_parse_sym_names
246
+ json = %{{"a":1,"b":[true,false]}}
247
+ obj = JSON.parse(json, :symbolize_names => true)
248
+ assert_equal({ :a => 1, :b => [true, false]}, obj)
249
+ end
250
+ def test_parse_additions
251
+ jam = Jam.new(true, 58)
252
+ json = Oj.dump(jam, :mode => :compat, :use_to_json => true)
253
+ obj = JSON.parse(json)
254
+ assert_equal(jam, obj)
255
+ obj = JSON.parse(json, :create_additions => true)
256
+ assert_equal(jam, obj)
257
+ obj = JSON.parse(json, :create_additions => false)
258
+ assert_equal({'json_class' => 'SharedMimicTest::Jam', 'x' => true, 'y' => 58}, obj)
259
+ json.gsub!('json_class', 'kson_class')
260
+ JSON.create_id = 'kson_class'
261
+ obj = JSON.parse(json, :create_additions => true)
262
+ JSON.create_id = 'json_class'
263
+ assert_equal(jam, obj)
264
+ end
265
+ def test_parse_bang
266
+ json = %{{"a":1,"b":[true,false]}}
267
+ obj = JSON.parse!(json)
268
+ assert_equal({ 'a' => 1, 'b' => [true, false]}, obj)
269
+ end
270
+
271
+ # recurse_proc
272
+ def test_recurse_proc
273
+ children = []
274
+ JSON.recurse_proc({ 'a' => 1, 'b' => [true, false]}) { |x| children << x }
275
+ # JRuby 1.7.0 rb_yield() is broken and converts the [true, false] array into true
276
+ unless 'jruby' == $ruby
277
+ assert([1, true, false, [true, false], { 'a' => 1, 'b' => [true, false]}] == children ||
278
+ [true, false, [true, false], 1, { 'b' => [true, false], 'a' => 1}] == children)
279
+ end
280
+ end
281
+
282
+ # make sure to_json is defined for object.
283
+ def test_mimic_to_json
284
+ {'a' => 1}.to_json()
285
+ Object.new().to_json()
286
+ end
287
+ end # SharedMimicTest
288
+
289
+ if defined?(ActiveSupport)
290
+ class SharedMimicRailsTest < SharedMimicTest
291
+ def test_activesupport_exception
292
+ begin
293
+ ActiveSupport::JSON.decode("{")
294
+ puts "Failed"
295
+ rescue ActiveSupport::JSON.parse_error
296
+ assert(true)
297
+ rescue Exception
298
+ assert(false, 'Expected a JSON::ParserError')
299
+ end
300
+ end
301
+
302
+ def test_activesupport_encode
303
+ Oj.default_options= {:indent => 0}
304
+ json = ActiveSupport::JSON.encode([1, true, nil])
305
+ assert_equal(%{[1,true,null]}, json)
306
+ end
307
+ end # SharedMimicRailsTest
308
+ end