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/perf_dump.rb ADDED
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ $: << '.'
5
+ $: << File.join(File.dirname(__FILE__), "../lib")
6
+ $: << File.join(File.dirname(__FILE__), "../ext")
7
+
8
+ require 'optparse'
9
+ require 'oj'
10
+
11
+ $verbose = false
12
+ $indent = 2
13
+ $iter = 100_000
14
+ $size = 2
15
+
16
+ opts = OptionParser.new
17
+ opts.on("-v", "verbose") { $verbose = true }
18
+ opts.on("-c", "--count [Int]", Integer, "iterations") { |i| $iter = i }
19
+ opts.on("-i", "--indent [Int]", Integer, "indentation") { |i| $indent = i }
20
+ opts.on("-s", "--size [Int]", Integer, "size (~Kbytes)") { |i| $size = i }
21
+ opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
22
+ files = opts.parse(ARGV)
23
+
24
+ $obj = {
25
+ 'a' => 'Alpha', # string
26
+ 'b' => true, # boolean
27
+ 'c' => 12345, # number
28
+ 'd' => [ true, [false, [-123456789, nil], 3.9676, ['Something else.', false], nil]], # mix it up array
29
+ 'e' => { 'zero' => nil, 'one' => 1, 'two' => 2, 'three' => [3], 'four' => [0, 1, 2, 3, 4] }, # hash
30
+ 'f' => nil, # nil
31
+ 'h' => { 'a' => { 'b' => { 'c' => { 'd' => {'e' => { 'f' => { 'g' => nil }}}}}}}, # deep hash, not that deep
32
+ 'i' => [[[[[[[nil]]]]]]] # deep array, again, not that deep
33
+ }
34
+
35
+ Oj.default_options = { :indent => $indent, :mode => :strict }
36
+
37
+ if 0 < $size
38
+ o = $obj
39
+ $obj = []
40
+ (4 * $size).times do
41
+ $obj << o
42
+ end
43
+ end
44
+
45
+ $json = Oj.dump($obj)
46
+ GC.start
47
+ start = Time.now
48
+ $iter.times { Oj.dump($obj) }
49
+ duration = Time.now - start
50
+ puts "Dumped #{$json.length} byte JSON #{$iter} times in %0.3f seconds or %0.3f iteration/sec." % [duration, $iter / duration]
data/test/perf_object.rb CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env ruby -wW1
1
+ #!/usr/bin/env ruby
2
2
 
3
3
  $: << '.'
4
4
  $: << '../lib'
data/test/perf_once.rb ADDED
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ $: << '.'
5
+ $: << File.join(File.dirname(__FILE__), "../lib")
6
+ $: << File.join(File.dirname(__FILE__), "../ext")
7
+
8
+ require 'oj'
9
+
10
+ filename = 'tmp.json'
11
+ File.open(filename, "w") { |f|
12
+ cnt = 0
13
+ f.puts('{')
14
+ ('a'..'z').each { |a|
15
+ ('a'..'z').each { |b|
16
+ ('a'..'z').each { |c|
17
+ ('a'..'z').each { |d|
18
+ f.puts(%|"#{a}#{b}#{c}#{d}":#{cnt},|)
19
+ cnt += 1
20
+ }
21
+ }
22
+ }
23
+ }
24
+ f.puts('"_last":0}')
25
+ }
26
+
27
+ def mem
28
+ `ps -o rss= -p #{$$}`.to_i
29
+ end
30
+
31
+ Oj.default_options = { mode: :strict, cache_keys: false, cache_str: -1 }
32
+ start = Time.now
33
+ Oj.load_file('tmp.json')
34
+ dur = Time.now - start
35
+ GC.start
36
+ puts "no cache duration: #{dur} @ #{mem}"
37
+
38
+ Oj.default_options = { cache_keys: true }
39
+ start = Time.now
40
+ Oj.load_file('tmp.json')
41
+ dur = Time.now - start
42
+ GC.start
43
+ puts "initial cache duration: #{dur} @ #{mem}"
44
+
45
+ start = Time.now
46
+ Oj.load_file('tmp.json')
47
+ dur = Time.now - start
48
+ GC.start
49
+ puts "second cache duration: #{dur} @ #{mem}"
50
+
51
+ 10.times{ GC.start }
52
+ start = Time.now
53
+ Oj.load_file('tmp.json')
54
+ dur = Time.now - start
55
+ GC.start
56
+ puts "after several GCs cache duration: #{dur} @ #{mem}"
57
+
58
+ # TBD check memory use
@@ -0,0 +1,189 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ $: << '.'
5
+ $: << File.join(File.dirname(__FILE__), "../lib")
6
+ $: << File.join(File.dirname(__FILE__), "../ext")
7
+
8
+ require 'optparse'
9
+ require 'perf'
10
+ require 'oj'
11
+ require 'json'
12
+
13
+ $verbose = false
14
+ $iter = 50_000
15
+ $with_bignum = false
16
+ $size = 1
17
+ $cache_keys = true
18
+ $symbol_keys = false
19
+
20
+ opts = OptionParser.new
21
+ opts.on("-v", "verbose") { $verbose = true }
22
+ opts.on("-c", "--count [Int]", Integer, "iterations") { |i| $iter = i }
23
+ opts.on("-s", "--size [Int]", Integer, "size (~Kbytes)") { |i| $size = i }
24
+ opts.on("-b", "with bignum") { $with_bignum = true }
25
+ opts.on("-k", "no cache") { $cache_keys = false }
26
+ opts.on("-sym", "symbol keys") { $symbol_keys = true }
27
+ opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
28
+ files = opts.parse(ARGV)
29
+
30
+ $obj = {
31
+ 'a' => 'Alpha', # string
32
+ 'b' => true, # boolean
33
+ 'c' => 12345, # number
34
+ 'd' => [ true, [false, [-123456789, nil], 3.9676, ['Something else.', false, 1, nil], nil]], # mix it up array
35
+ 'e' => { 'zero' => nil, 'one' => 1, 'two' => 2, 'three' => [3], 'four' => [0, 1, 2, 3, 4] }, # hash
36
+ 'f' => nil, # nil
37
+ 'h' => { 'a' => { 'b' => { 'c' => { 'd' => {'e' => { 'f' => { 'g' => nil }}}}}}}, # deep hash, not that deep
38
+ 'i' => [[[[[[[nil]]]]]]] # deep array, again, not that deep
39
+ }
40
+ $obj['g'] = 12345678901234567890123456789 if $with_bignum
41
+
42
+ if 0 < $size
43
+ o = $obj
44
+ $obj = []
45
+ (4 * $size).times do
46
+ $obj << o
47
+ end
48
+ end
49
+
50
+ $json = Oj.dump($obj)
51
+ $failed = {} # key is same as String used in tests later
52
+ Oj.default_options = {create_id: '^', create_additions: true, class_cache: true}
53
+ if $cache_keys
54
+ Oj.default_options = {cache_keys: true, cache_str: 6, symbol_keys: $symbol_keys}
55
+ else
56
+ Oj.default_options = {cache_keys: false, cache_str: -1, symbol_keys: $symbol_keys}
57
+ end
58
+ JSON.parser = JSON::Ext::Parser
59
+
60
+ class AllSaj
61
+ def initialize()
62
+ end
63
+
64
+ def hash_start(key)
65
+ end
66
+
67
+ def hash_end(key)
68
+ end
69
+
70
+ def array_start(key)
71
+ end
72
+
73
+ def array_end(key)
74
+ end
75
+
76
+ def add_value(value, key)
77
+ end
78
+ end # AllSaj
79
+
80
+ class NoSaj
81
+ def initialize()
82
+ end
83
+ end # NoSaj
84
+
85
+ no_handler = NoSaj.new()
86
+ all_handler = AllSaj.new()
87
+
88
+ if $verbose
89
+ puts "json:\n#{$json}\n"
90
+ end
91
+
92
+ ### Validate ######################
93
+ p_val = Oj::Parser.new(:validate)
94
+
95
+ puts '-' * 80
96
+ puts "Validate Performance"
97
+ perf = Perf.new()
98
+ perf.add('Oj::Parser.validate', 'none') { p_val.parse($json) }
99
+ perf.add('Oj::Saj.none', 'none') { Oj.saj_parse(no_handler, $json) }
100
+ perf.run($iter)
101
+
102
+ ### SAJ ######################
103
+ p_all = Oj::Parser.new(:saj)
104
+ p_all.handler = all_handler
105
+ p_all.cache_keys = $cache_keys
106
+ p_all.cache_strings = 6
107
+
108
+ puts '-' * 80
109
+ puts "Parse Callback Performance"
110
+ perf = Perf.new()
111
+ perf.add('Oj::Parser.saj', 'all') { p_all.parse($json) }
112
+ perf.add('Oj::Saj.all', 'all') { Oj.saj_parse(all_handler, $json) }
113
+ perf.run($iter)
114
+
115
+ ### Usual ######################
116
+ p_usual = Oj::Parser.new(:usual)
117
+ p_usual.cache_keys = $cache_keys
118
+ p_usual.cache_strings = ($cache_keys ? 6 : 0)
119
+ p_usual.symbol_keys = $symbol_keys
120
+
121
+ puts '-' * 80
122
+ puts "Parse Usual Performance"
123
+ perf = Perf.new()
124
+ perf.add('Oj::Parser.usual', '') { p_usual.parse($json) }
125
+ perf.add('Oj::strict_load', '') { Oj.strict_load($json) }
126
+ perf.add('JSON::Ext', 'parse') { JSON.load($json) }
127
+ perf.run($iter)
128
+
129
+ ### Usual Objects ######################
130
+
131
+ # Original Oj follows the JSON gem for creating objects which uses the class
132
+ # json_create(arg) method. Oj::Parser in usual mode supprts the same but also
133
+ # handles populating the object variables directly which is faster.
134
+
135
+ class Stuff
136
+ attr_accessor :alpha, :bravo, :charlie, :delta, :echo, :foxtrot, :golf, :hotel, :india, :juliet
137
+ def self.json_create(arg)
138
+ obj = self.new
139
+ obj.alpha = arg["alpha"]
140
+ obj.bravo = arg["bravo"]
141
+ obj.charlie = arg["charlie"]
142
+ obj.delta = arg["delta"]
143
+ obj.echo = arg["echo"]
144
+ obj.foxtrot = arg["foxtrot"]
145
+ obj.golf = arg["golf"]
146
+ obj.hotel = arg["hotel"]
147
+ obj.india = arg["india"]
148
+ obj.juliet = arg["juliet"]
149
+ obj
150
+ end
151
+ end
152
+
153
+ $obj_json = %|{
154
+ "alpha": [0, 1,2,3,4,5,6,7,8,9],
155
+ "bravo": true,
156
+ "charlie": 123,
157
+ "delta": "some string",
158
+ "echo": null,
159
+ "^": "Stuff",
160
+ "foxtrot": false,
161
+ "golf": "gulp",
162
+ "hotel": {"x": true, "y": false},
163
+ "india": [null, true, 123],
164
+ "juliet": "junk"
165
+ }|
166
+
167
+
168
+ p_usual = Oj::Parser.new(:usual)
169
+ p_usual.cache_keys = $cache_keys
170
+ p_usual.cache_strings = ($cache_keys ? 6 : 0)
171
+ p_usual.symbol_keys = $symbol_keys
172
+ p_usual.create_id = '^'
173
+ p_usual.class_cache = true
174
+ p_usual.ignore_json_create = true
175
+
176
+ JSON.create_id = '^'
177
+
178
+ puts '-' * 80
179
+ puts "Parse Usual Object Performance"
180
+ perf = Perf.new()
181
+ perf.add('Oj::Parser.usual', '') { p_usual.parse($obj_json) }
182
+ perf.add('Oj::compat_load', '') { Oj.compat_load($obj_json) }
183
+ perf.add('JSON::Ext', 'parse') { JSON.load($obj_json) }
184
+ perf.run($iter)
185
+
186
+ unless $failed.empty?
187
+ puts "The following packages were not included for the reason listed"
188
+ $failed.each { |tag,msg| puts "***** #{tag}: #{msg}" }
189
+ end
data/test/perf_scp.rb CHANGED
@@ -14,16 +14,16 @@ require 'oj'
14
14
 
15
15
  $verbose = false
16
16
  $indent = 0
17
- $iter = 50000
17
+ $iter = 50_000
18
18
  $with_bignum = false
19
- $size = 0
19
+ $size = 1
20
20
 
21
21
  opts = OptionParser.new
22
22
  opts.on("-v", "verbose") { $verbose = true }
23
23
  opts.on("-c", "--count [Int]", Integer, "iterations") { |i| $iter = i }
24
24
  opts.on("-i", "--indent [Int]", Integer, "indentation") { |i| $indent = i }
25
- opts.on("-s", "--size [Int]", Integer, "size (~Kbytes)") { |i| $size = i }
26
- opts.on("-b", "with bignum") { $with_bignum = true }
25
+ opts.on("-s", "--size [Int]", Integer, "size (~Kbytes)") { |i| $size = i }
26
+ opts.on("-b", "with bignum") { $with_bignum = true }
27
27
  opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
28
28
  files = opts.parse(ARGV)
29
29
 
@@ -47,7 +47,7 @@ if 0 < $size
47
47
  end
48
48
  end
49
49
 
50
- Oj.default_options = { :indent => $indent, :mode => :compat }
50
+ Oj.default_options = { :indent => $indent, :mode => :strict, cache_keys: true, cache_str: 5 }
51
51
 
52
52
  $json = Oj.dump($obj)
53
53
  $failed = {} # key is same as String used in tests later
@@ -105,7 +105,7 @@ class AllHandler < Oj::ScHandler
105
105
 
106
106
  def hash_set(h, key, value)
107
107
  end
108
-
108
+
109
109
  def array_append(a, value)
110
110
  end
111
111
 
@@ -137,10 +137,11 @@ end
137
137
  puts '-' * 80
138
138
  puts "Parse Performance"
139
139
  perf = Perf.new()
140
- perf.add('Oj::Saj', 'all') { Oj.saj_parse(saj_handler, $json) }
141
- perf.add('Oj::Saj', 'none') { Oj.saj_parse(no_saj, $json) }
142
- perf.add('Oj::Scp', 'all') { Oj.sc_parse(sc_handler, $json) }
143
- perf.add('Oj::Scp', 'none') { Oj.sc_parse(no_handler, $json) }
140
+ perf.add('Oj::Saj.all', 'all') { Oj.saj_parse(saj_handler, $json) }
141
+ perf.add('Oj::Saj.none', 'none') { Oj.saj_parse(no_saj, $json) }
142
+ perf.add('Oj::Scp.all', 'all') { Oj.sc_parse(sc_handler, $json) }
143
+ perf.add('Oj::Scp.none', 'none') { Oj.sc_parse(no_handler, $json) }
144
+ perf.add('Oj::load', 'none') { Oj.wab_load($json) }
144
145
  perf.add('Yajl', 'parse') { Yajl::Parser.parse($json) } unless $failed.has_key?('Yajl')
145
146
  perf.add('JSON::Ext', 'parse') { JSON::Ext::Parser.new($json).parse } unless $failed.has_key?('JSON::Ext')
146
147
  perf.run($iter)
data/test/perf_strict.rb CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env ruby -wW1
1
+ #!/usr/bin/env ruby
2
2
  # encoding: UTF-8
3
3
 
4
4
  $: << '.'
@@ -15,6 +15,8 @@ $iter = 20000
15
15
  $with_bignum = false
16
16
  $with_nums = true
17
17
  $size = 0
18
+ $symbolize = false
19
+ $cache_keys = true
18
20
 
19
21
  opts = OptionParser.new
20
22
  opts.on("-v", "verbose") { $verbose = true }
@@ -23,6 +25,8 @@ opts.on("-i", "--indent [Int]", Integer, "indentation") { |i| $indent = i }
23
25
  opts.on("-s", "--size [Int]", Integer, "size (~Kbytes)") { |i| $size = i }
24
26
  opts.on("-b", "with bignum") { $with_bignum = true }
25
27
  opts.on("-n", "without numbers") { $with_nums = false }
28
+ opts.on("-z", "--symbolize", "symbolize keys") { $symbolize = true }
29
+ opts.on("-k", "--no-cache", "turn off key caching") { $cache_keys = false }
26
30
  opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
27
31
  files = opts.parse(ARGV)
28
32
 
@@ -51,7 +55,7 @@ else
51
55
  }
52
56
  end
53
57
 
54
- Oj.default_options = { :indent => $indent, :mode => :strict }
58
+ Oj.default_options = { :indent => $indent, :mode => :strict, cache_keys: $cache_keys, cache_str: 5 }
55
59
 
56
60
  if 0 < $size
57
61
  o = $obj
@@ -62,9 +66,6 @@ if 0 < $size
62
66
  end
63
67
 
64
68
  $json = Oj.dump($obj)
65
- $obj_json = Oj.dump($obj, :mode => :object)
66
- #puts "*** size: #{$obj_json.size}"
67
- #puts "*** #{$obj_json}"
68
69
  $failed = {} # key is same as String used in tests later
69
70
 
70
71
  def capture_error(tag, orig, load_key, dump_key, &blk)
@@ -77,8 +78,13 @@ def capture_error(tag, orig, load_key, dump_key, &blk)
77
78
  end
78
79
 
79
80
  # Verify that all packages dump and load correctly and return the same Object as the original.
80
- capture_error('Oj:strict', $obj, 'load', 'dump') { |o| Oj.strict_load(Oj.dump(o, :mode => :strict)) }
81
- capture_error('Yajl', $obj, 'encode', 'parse') { |o| require 'yajl'; Yajl::Parser.parse(Yajl::Encoder.encode(o)) }
81
+ capture_error('Oj:strict', $obj, 'load', 'dump') { |o|
82
+ Oj.strict_load(Oj.dump(o))
83
+ }
84
+ capture_error('Yajl', $obj, 'encode', 'parse') { |o|
85
+ require 'yajl'
86
+ Yajl::Parser.parse(Yajl::Encoder.encode(o))
87
+ }
82
88
  capture_error('JSON::Ext', $obj, 'generate', 'parse') { |o|
83
89
  require 'json'
84
90
  require 'json/ext'
@@ -86,16 +92,11 @@ capture_error('JSON::Ext', $obj, 'generate', 'parse') { |o|
86
92
  JSON.parser = JSON::Ext::Parser
87
93
  JSON.parse(JSON.generate(o))
88
94
  }
89
- capture_error('JSON::Pure', $obj, 'generate', 'parse') { |o|
90
- require 'json/pure'
91
- JSON.generator = JSON::Pure::Generator
92
- JSON.parser = JSON::Pure::Parser
93
- JSON.parse(JSON.generate(o))
94
- }
95
+
96
+ Oj.default_options = { symbol_keys: $symbolize }
95
97
 
96
98
  if $verbose
97
99
  puts "json:\n#{$json}\n"
98
- puts "object json:\n#{$obj_json}\n"
99
100
  puts "Oj loaded object:\n#{Oj.strict_load($json)}\n"
100
101
  puts "Yajl loaded object:\n#{Yajl::Parser.parse($json)}\n"
101
102
  puts "JSON loaded object:\n#{JSON::Ext::Parser.new($json).parse}\n"
@@ -105,19 +106,29 @@ puts '-' * 80
105
106
  puts "Strict Parse Performance"
106
107
  perf = Perf.new()
107
108
  unless $failed.has_key?('JSON::Ext')
108
- perf.add('JSON::Ext', 'parse') { JSON.parse($json) }
109
+ perf.add('JSON::Ext', 'parse') { JSON.parse($json, symbolize_names: $symbolize) }
109
110
  perf.before('JSON::Ext') { JSON.parser = JSON::Ext::Parser }
110
111
  end
111
- unless $failed.has_key?('JSON::Pure')
112
- perf.add('JSON::Pure', 'parse') { JSON.parse($json) }
113
- perf.before('JSON::Pure') { JSON.parser = JSON::Pure::Parser }
114
- end
115
112
  unless $failed.has_key?('Oj:strict')
116
113
  perf.add('Oj:strict', 'strict_load') { Oj.strict_load($json) }
114
+ perf.add('Oj:wab', 'wab_load') { Oj.wab_load($json) }
117
115
  end
118
116
  perf.add('Yajl', 'parse') { Yajl::Parser.parse($json) } unless $failed.has_key?('Yajl')
119
117
  perf.run($iter)
120
118
 
119
+ puts '-' * 80
120
+ puts "Strict Dump Performance"
121
+ perf = Perf.new()
122
+ unless $failed.has_key?('JSON::Ext')
123
+ perf.add('JSON::Ext', 'dump') { JSON.generate($obj) }
124
+ perf.before('JSON::Ext') { JSON.generator = JSON::Ext::Generator }
125
+ end
126
+ unless $failed.has_key?('Oj:strict')
127
+ perf.add('Oj:strict', 'dump') { Oj.dump($obj) }
128
+ end
129
+ perf.add('Yajl', 'encode') { Yajl::Encoder.encode($obj) } unless $failed.has_key?('Yajl')
130
+ perf.run($iter)
131
+
121
132
  puts
122
133
  puts '-' * 80
123
134
  puts
data/test/perf_wab.rb ADDED
@@ -0,0 +1,131 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ $: << '.'
5
+ $: << File.join(File.dirname(__FILE__), "../lib")
6
+ $: << File.join(File.dirname(__FILE__), "../ext")
7
+
8
+ require 'optparse'
9
+ require 'perf'
10
+ require 'oj'
11
+
12
+ $verbose = false
13
+ $indent = 0
14
+ $iter = 20000
15
+ $with_bignum = false
16
+ $with_nums = true
17
+ $size = 0
18
+
19
+ opts = OptionParser.new
20
+ opts.on("-v", "verbose") { $verbose = true }
21
+ opts.on("-c", "--count [Int]", Integer, "iterations") { |i| $iter = i }
22
+ opts.on("-i", "--indent [Int]", Integer, "indentation") { |i| $indent = i }
23
+ opts.on("-s", "--size [Int]", Integer, "size (~Kbytes)") { |i| $size = i }
24
+ opts.on("-b", "with bignum") { $with_bignum = true }
25
+ opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
26
+ files = opts.parse(ARGV)
27
+
28
+ $obj = {
29
+ a: 'Alpha', # string
30
+ b: true, # boolean
31
+ c: 12345, # number
32
+ d: [ true, [false, [-123456789, nil], 3.9676, ['Something else.', false], nil]], # mix it up array
33
+ e: { zero: nil, one: 1, two: 2, three: [3], four: [0, 1, 2, 3, 4] }, # hash
34
+ f: nil, # nil
35
+ h: { a: { b: { c: { d: {e: { f: { g: nil }}}}}}}, # deep hash, not that deep
36
+ i: [[[[[[[nil]]]]]]] # deep array, again, not that deep
37
+ }
38
+ $obj[:g] = 12345678901234567890123456789 if $with_bignum
39
+
40
+ Oj.default_options = { :indent => $indent, :mode => :wab }
41
+
42
+ if 0 < $size
43
+ o = $obj
44
+ $obj = []
45
+ (4 * $size).times do
46
+ $obj << o
47
+ end
48
+ end
49
+
50
+ $json = Oj.dump($obj)
51
+ $obj_json = Oj.dump($obj, :mode => :object)
52
+ #puts "*** size: #{$obj_json.size}"
53
+ #puts "*** #{$obj_json}"
54
+ $failed = {} # key is same as String used in tests later
55
+
56
+ def capture_error(tag, orig, load_key, dump_key, &blk)
57
+ begin
58
+ obj = blk.call(orig)
59
+ raise "#{tag} #{dump_key} and #{load_key} did not return the same object as the original." unless orig == obj
60
+ rescue Exception => e
61
+ $failed[tag] = "#{e.class}: #{e.message}"
62
+ end
63
+ end
64
+
65
+ # Verify that all packages dump and load correctly and return the same Object as the original.
66
+ capture_error('Oj:wab', $obj, 'load', 'dump') { |o| Oj.wab_load(Oj.dump(o, :mode => :wab)) }
67
+ capture_error('Yajl', $obj, 'encode', 'parse') { |o| require 'yajl'; Yajl::Parser.parse(Yajl::Encoder.encode(o)) }
68
+ capture_error('JSON::Ext', $obj, 'generate', 'parse') { |o|
69
+ require 'json'
70
+ require 'json/ext'
71
+ JSON.generator = JSON::Ext::Generator
72
+ JSON.parser = JSON::Ext::Parser
73
+ JSON.parse(JSON.generate(o))
74
+ }
75
+ capture_error('JSON::Pure', $obj, 'generate', 'parse') { |o|
76
+ require 'json/pure'
77
+ JSON.generator = JSON::Pure::Generator
78
+ JSON.parser = JSON::Pure::Parser
79
+ JSON.parse(JSON.generate(o))
80
+ }
81
+
82
+ if $verbose
83
+ puts "json:\n#{$json}\n"
84
+ puts "object json:\n#{$obj_json}\n"
85
+ puts "Oj loaded object:\n#{Oj.wab_load($json)}\n"
86
+ puts "Yajl loaded object:\n#{Yajl::Parser.parse($json)}\n"
87
+ puts "JSON loaded object:\n#{JSON::Ext::Parser.new($json).parse}\n"
88
+ end
89
+
90
+ puts '-' * 80
91
+ puts "Wab Parse Performance"
92
+ perf = Perf.new()
93
+ unless $failed.has_key?('JSON::Ext')
94
+ perf.add('JSON::Ext', 'parse') { JSON.parse($json) }
95
+ perf.before('JSON::Ext') { JSON.parser = JSON::Ext::Parser }
96
+ end
97
+ unless $failed.has_key?('JSON::Pure')
98
+ perf.add('JSON::Pure', 'parse') { JSON.parse($json) }
99
+ perf.before('JSON::Pure') { JSON.parser = JSON::Pure::Parser }
100
+ end
101
+ unless $failed.has_key?('Oj:wab')
102
+ perf.add('Oj:wab', 'wab_load') { Oj.wab_load($json) }
103
+ end
104
+ perf.add('Yajl', 'parse') { Yajl::Parser.parse($json) } unless $failed.has_key?('Yajl')
105
+ perf.run($iter)
106
+
107
+ puts '-' * 80
108
+ puts "Wab Dump Performance"
109
+ perf = Perf.new()
110
+ unless $failed.has_key?('JSON::Ext')
111
+ perf.add('JSON::Ext', 'dump') { JSON.generate($obj) }
112
+ perf.before('JSON::Ext') { JSON.generator = JSON::Ext::Generator }
113
+ end
114
+ unless $failed.has_key?('JSON::Pure')
115
+ perf.add('JSON::Pure', 'generate') { JSON.generate($obj) }
116
+ perf.before('JSON::Pure') { JSON.generator = JSON::Pure::Generator }
117
+ end
118
+ unless $failed.has_key?('Oj:wab')
119
+ perf.add('Oj:wab', 'dump') { Oj.dump($obj, :mode => :wab) }
120
+ end
121
+ perf.add('Yajl', 'encode') { Yajl::Encoder.encode($obj) } unless $failed.has_key?('Yajl')
122
+ perf.run($iter)
123
+
124
+ puts
125
+ puts '-' * 80
126
+ puts
127
+
128
+ unless $failed.empty?
129
+ puts "The following packages were not included for the reason listed"
130
+ $failed.each { |tag,msg| puts "***** #{tag}: #{msg}" }
131
+ end
data/test/prec.rb ADDED
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'oj'
4
+
5
+ extras = {"locationLng" => -97.14690769100295}
6
+
7
+ Oj.default_options = {float_precision: 17}
8
+
9
+ encoded = Oj.dump(extras)
10
+ puts encoded
11
+ puts Oj.load(encoded)
12
+
13
+ require "active_record"
14
+
15
+ Oj::Rails.set_encoder()
16
+ Oj::Rails.set_decoder()
17
+
18
+ Oj.default_options = {float_precision: 17}
19
+ # Using Oj rails encoder, gets the correct value: {"locationLng":-97.14690769100295}
20
+ encoded = ActiveSupport::JSON.encode(extras)
21
+ puts encoded
22
+ puts ActiveSupport::JSON.decode(encoded)
23
+ puts Oj.load(encoded)
data/test/sample.rb CHANGED
@@ -10,7 +10,6 @@ end
10
10
  require 'pp'
11
11
  require 'sample/doc'
12
12
 
13
-
14
13
  def sample_doc(size=3)
15
14
  colors = [ :black, :gray, :white, :red, :blue, :yellow, :green, :purple, :orange ]
16
15
 
data/test/sample_json.rb CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env ruby -wW2
1
+ #!/usr/bin/env ruby
2
2
 
3
3
  if $0 == __FILE__
4
4
  $: << '.'