oj 2.18.3 → 3.13.14

Sign up to get free protection for your applications and to get access to all the features.
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/lib/oj/json.rb ADDED
@@ -0,0 +1,176 @@
1
+
2
+ require 'ostruct'
3
+ require 'oj/state'
4
+
5
+ module JSON
6
+ NaN = 0.0/0.0 unless defined?(::JSON::NaN)
7
+ Infinity = 1.0/0.0 unless defined?(::JSON::Infinity)
8
+ MinusInfinity = -1.0/0.0 unless defined?(::JSON::MinusInfinity)
9
+ # Taken from the unit test. Note that items like check_circular? are not
10
+ # present.
11
+ PRETTY_STATE_PROTOTYPE = Ext::Generator::State.from_state({
12
+ :allow_nan => false,
13
+ :array_nl => "\n",
14
+ :ascii_only => false,
15
+ :buffer_initial_length => 1024,
16
+ :depth => 0,
17
+ :indent => " ",
18
+ :max_nesting => 100,
19
+ :object_nl => "\n",
20
+ :space => " ",
21
+ :space_before => "",
22
+ }) unless defined?(::JSON::PRETTY_STATE_PROTOTYPE)
23
+ SAFE_STATE_PROTOTYPE = Ext::Generator::State.from_state({
24
+ :allow_nan => false,
25
+ :array_nl => "",
26
+ :ascii_only => false,
27
+ :buffer_initial_length => 1024,
28
+ :depth => 0,
29
+ :indent => "",
30
+ :max_nesting => 100,
31
+ :object_nl => "",
32
+ :space => "",
33
+ :space_before => "",
34
+ }) unless defined?(::JSON::SAFE_STATE_PROTOTYPE)
35
+ FAST_STATE_PROTOTYPE = Ext::Generator::State.from_state({
36
+ :allow_nan => false,
37
+ :array_nl => "",
38
+ :ascii_only => false,
39
+ :buffer_initial_length => 1024,
40
+ :depth => 0,
41
+ :indent => "",
42
+ :max_nesting => 0,
43
+ :object_nl => "",
44
+ :space => "",
45
+ :space_before => "",
46
+ }) unless defined?(::JSON::FAST_STATE_PROTOTYPE)
47
+
48
+ def self.dump_default_options
49
+ Oj::MimicDumpOption.new
50
+ end
51
+
52
+ def self.dump_default_options=(h)
53
+ m = Oj::MimicDumpOption.new
54
+ h.each do |k,v|
55
+ m[k] = v
56
+ end
57
+ end
58
+
59
+ def self.parser=(p)
60
+ @@parser = p
61
+ end
62
+
63
+ def self.parser()
64
+ @@parser
65
+ end
66
+
67
+ def self.generator=(g)
68
+ @@generator = g
69
+ end
70
+
71
+ def self.generator()
72
+ @@generator
73
+ end
74
+
75
+ module Ext
76
+ class Parser
77
+ def initialize(src)
78
+ raise TypeError.new("already initialized") unless @source.nil?
79
+ @source = src
80
+ end
81
+
82
+ def source()
83
+ raise TypeError.new("already initialized") if @source.nil?
84
+ @source
85
+ end
86
+
87
+ def parse()
88
+ raise TypeError.new("already initialized") if @source.nil?
89
+ JSON.parse(@source)
90
+ end
91
+
92
+ end # Parser
93
+ end # Ext
94
+
95
+ State = ::JSON::Ext::Generator::State unless defined?(::JSON::State)
96
+
97
+ begin
98
+ send(:remove_const, :Parser)
99
+ rescue
100
+ end
101
+ Parser = ::JSON::Ext::Parser unless defined?(::JSON::Parser)
102
+ self.parser = ::JSON::Ext::Parser
103
+ self.generator = ::JSON::Ext::Generator
104
+
105
+ # Taken directly from the json gem. Shamelessly copied. It is similar in
106
+ # some ways to the Oj::Bag class or the Oj::EasyHash class.
107
+ class GenericObject < OpenStruct
108
+ class << self
109
+ alias [] new
110
+
111
+ def json_creatable?
112
+ @json_creatable
113
+ end
114
+
115
+ attr_writer :json_creatable
116
+
117
+ def json_create(data)
118
+ data = data.dup
119
+ data.delete JSON.create_id
120
+ self[data]
121
+ end
122
+
123
+ def from_hash(object)
124
+ case
125
+ when object.respond_to?(:to_hash)
126
+ result = new
127
+ object.to_hash.each do |key, value|
128
+ result[key] = from_hash(value)
129
+ end
130
+ result
131
+ when object.respond_to?(:to_ary)
132
+ object.to_ary.map { |a| from_hash(a) }
133
+ else
134
+ object
135
+ end
136
+ end
137
+
138
+ def load(source, proc = nil, opts = {})
139
+ result = ::JSON.load(source, proc, opts.merge(:object_class => self))
140
+ result.nil? ? new : result
141
+ end
142
+
143
+ def dump(obj, *args)
144
+ ::JSON.dump(obj, *args)
145
+ end
146
+
147
+ end # self
148
+
149
+ self.json_creatable = false
150
+
151
+ def to_hash
152
+ table
153
+ end
154
+
155
+ def [](name)
156
+ __send__(name)
157
+ end unless method_defined?(:[])
158
+
159
+ def []=(name, value)
160
+ __send__("#{name}=", value)
161
+ end unless method_defined?(:[]=)
162
+
163
+ def |(other)
164
+ self.class[other.to_hash.merge(to_hash)]
165
+ end
166
+
167
+ def as_json(*)
168
+ { JSON.create_id => self.class.name }.merge to_hash
169
+ end
170
+
171
+ def to_json(*a)
172
+ as_json.to_json(*a)
173
+ end
174
+ end
175
+
176
+ end # JSON
data/lib/oj/mimic.rb CHANGED
@@ -1,4 +1,5 @@
1
1
 
2
+ require 'bigdecimal'
2
3
  begin
3
4
  require 'ostruct'
4
5
  rescue Exception
@@ -7,6 +8,52 @@ end
7
8
 
8
9
  module Oj
9
10
 
11
+ ##
12
+ # Custom mode can be used to emulate the compat mode with some minor
13
+ # differences. These are the options that setup the custom mode to be like
14
+ # the compat mode.
15
+ CUSTOM_MIMIC_JSON_OPTIONS = {
16
+ allow_gc: true,
17
+ allow_invalid_unicode: false,
18
+ allow_nan: false,
19
+ array_class: nil,
20
+ array_nl: nil,
21
+ auto_define: false,
22
+ bigdecimal_as_decimal: false,
23
+ bigdecimal_load: :auto,
24
+ circular: false,
25
+ class_cache: false,
26
+ cache_keys: true,
27
+ cache_str: 5,
28
+ create_additions: false,
29
+ create_id: "json_class",
30
+ empty_string: false,
31
+ escape_mode: :unicode_xss,
32
+ float_precision: 0,
33
+ hash_class: nil,
34
+ ignore: nil,
35
+ ignore_under: false,
36
+ indent: 0,
37
+ integer_range: nil,
38
+ mode: :custom,
39
+ nan: :raise,
40
+ nilnil: false,
41
+ object_nl: nil,
42
+ omit_nil: false,
43
+ quirks_mode: true,
44
+ safe: false,
45
+ second_precision: 3,
46
+ space: nil,
47
+ space_before: nil,
48
+ symbol_keys: false,
49
+ time_format: :ruby,
50
+ trace: false,
51
+ use_as_json: false,
52
+ use_raw_json: false,
53
+ use_to_hash: false,
54
+ use_to_json: true,
55
+ }
56
+
10
57
  # A bit hack-ish but does the trick. The JSON.dump_default_options is a Hash
11
58
  # but in mimic we use a C struct to store defaults. This class creates a view
12
59
  # onto that struct.
@@ -29,20 +76,25 @@ module Oj
29
76
  end
30
77
  end
31
78
 
79
+ # Loads mimic-ed JSON paths. Used by Oj.mimic_JSON().
80
+ # @param mimic_paths [Array] additional paths to add to the Ruby loaded features.
32
81
  def self.mimic_loaded(mimic_paths=[])
33
82
  $LOAD_PATH.each do |d|
34
83
  next unless File.exist?(d)
35
84
 
36
85
  jfile = File.join(d, 'json.rb')
37
86
  $LOADED_FEATURES << jfile unless $LOADED_FEATURES.include?(jfile) if File.exist?(jfile)
38
-
87
+
39
88
  Dir.glob(File.join(d, 'json', '**', '*.rb')).each do |file|
40
- $LOADED_FEATURES << file unless $LOADED_FEATURES.include?(file)
89
+ # allow json/add/xxx to be loaded. User can override with Oj.add_to_json(xxx).
90
+ $LOADED_FEATURES << file unless $LOADED_FEATURES.include?(file) unless file.include?('add')
41
91
  end
42
92
  end
43
93
  mimic_paths.each { |p| $LOADED_FEATURES << p }
44
94
  $LOADED_FEATURES << 'json' unless $LOADED_FEATURES.include?('json')
45
95
 
96
+ require 'oj/json'
97
+
46
98
  if Object.const_defined?('OpenStruct')
47
99
  OpenStruct.class_eval do
48
100
  # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
@@ -54,8 +106,87 @@ module Oj
54
106
  end
55
107
  end
56
108
  def self.json_create(h)
57
- new(h['t'])
109
+ new(h['t'] || h[:t])
110
+ end
111
+ end
112
+ end
113
+
114
+ BigDecimal.class_eval do
115
+ # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
116
+ unless defined?(self.as_json)
117
+ def as_json(*)
118
+ {JSON.create_id => 'BigDecimal', 'b' => _dump }
119
+ end
120
+ end
121
+ def self.json_create(h)
122
+ BigDecimal._load(h['b'])
123
+ end
124
+ end
125
+
126
+ Complex.class_eval do
127
+ # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
128
+ unless defined?(self.as_json)
129
+ def as_json(*)
130
+ {JSON.create_id => 'Complex', 'r' => real, 'i' => imag }
131
+ end
132
+ end
133
+ def self.json_create(h)
134
+ Complex(h['r'], h['i'])
135
+ end
136
+ end
137
+
138
+ DateTime.class_eval do
139
+ # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
140
+ unless defined?(self.as_json)
141
+ def as_json(*)
142
+ { JSON.create_id => 'DateTime',
143
+ 'y' => year,
144
+ 'm' => month,
145
+ 'd' => day,
146
+ 'H' => hour,
147
+ 'M' => min,
148
+ 'S' => sec,
149
+ 'of' => offset.to_s,
150
+ 'sg' => start }
151
+ end
152
+ end
153
+ def self.json_create(h)
154
+ # offset is a rational as a string
155
+ as, bs = h['of'].split('/')
156
+ a = as.to_i
157
+ b = bs.to_i
158
+ if 0 == b
159
+ off = a
160
+ else
161
+ off = Rational(a, b)
58
162
  end
163
+ civil(h['y'], h['m'], h['d'], h['H'], h['M'], h['S'], off, h['sg'])
164
+ end
165
+ end
166
+
167
+ Date.class_eval do
168
+ # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
169
+ unless defined?(self.as_json)
170
+ def as_json(*)
171
+ { JSON.create_id => 'Date', 'y' => year, 'm' => month, 'd' => day, 'sg' => start }
172
+ end
173
+ end
174
+ def self.json_create(h)
175
+ civil(h['y'], h['m'], h['d'], h['sg'])
176
+ end
177
+ end
178
+
179
+ Exception.class_eval do
180
+ # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
181
+ unless defined?(self.as_json)
182
+ def as_json(*)
183
+ {JSON.create_id => self.class.name, 'm' => message, 'b' => backtrace }
184
+ end
185
+ end
186
+ def self.json_create(h)
187
+ e = new(h['m'])
188
+ e.set_backtrace(h['b'])
189
+ e
59
190
  end
60
191
  end
61
192
 
@@ -67,7 +198,7 @@ module Oj
67
198
  end
68
199
  end
69
200
  def self.json_create(h)
70
- new(h['a'])
201
+ new(*h['a'])
71
202
  end
72
203
  end
73
204
 
@@ -105,7 +236,7 @@ module Oj
105
236
  end
106
237
  end
107
238
  def self.json_create(h)
108
- new(h['v'])
239
+ new(*h['v'])
109
240
  end
110
241
  end
111
242
 
@@ -125,7 +256,6 @@ module Oj
125
256
  # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
126
257
  unless defined?(self.as_json)
127
258
  def as_json(*)
128
- {JSON.create_id => 'Symbol', 's' => to_s }
129
259
  nsecs = [ tv_usec * 1000 ]
130
260
  nsecs << tv_nsec if respond_to?(:tv_nsec)
131
261
  nsecs = nsecs.max
@@ -144,19 +274,28 @@ module Oj
144
274
  end
145
275
  end
146
276
 
147
- JSON.module_eval do
148
- def self.dump_default_options
149
- Oj::MimicDumpOption.new
150
- end
151
-
152
- def self.dump_default_options=(h)
153
- m = Oj::MimicDumpOption.new
154
- h.each do |k,v|
155
- m[k] = v
156
- end
157
- end
158
- end
159
-
160
277
  end # self.mimic_loaded
161
278
 
162
279
  end # Oj
280
+
281
+ # More monkey patches.
282
+ class String
283
+ def to_json_raw_object
284
+ {
285
+ JSON.create_id => self.class.name,
286
+ 'raw' => self.bytes
287
+ }
288
+ end
289
+ def to_json_raw(*)
290
+ to_json_raw_object().to_json()
291
+ end
292
+ def self.json_create(obj)
293
+ s = ''
294
+ s.encode!(Encoding::ASCII_8BIT) if s.respond_to?(:encode!)
295
+ raw = obj['raw']
296
+ if raw.is_a? Array
297
+ raw.each { |v| s << v }
298
+ end
299
+ s
300
+ end
301
+ end
data/lib/oj/state.rb ADDED
@@ -0,0 +1,132 @@
1
+
2
+ module JSON
3
+ module Ext
4
+ module Generator
5
+ unless defined?(::JSON::Ext::Generator::State)
6
+ # This class exists for json gem compatibility only. While it can be
7
+ # used as the options for other than compatibility a simple Hash is
8
+ # recommended as it is simpler and performs better. The only bit
9
+ # missing by not using a state object is the depth availability which
10
+ # may be the depth during dumping or maybe not since it can be set and
11
+ # the docs for depth= is the same as max_nesting. Note: Had to make
12
+ # this a subclass of Object instead of Hash like EashyHash due to
13
+ # conflicts with the json gem.
14
+ class State
15
+
16
+ def self.from_state(opts)
17
+ s = self.new()
18
+ s.clear()
19
+ s.merge(opts)
20
+ s
21
+ end
22
+
23
+ def initialize(opts = {})
24
+ @attrs = {}
25
+
26
+ # Populate with all vars then merge in opts. This class deviates from
27
+ # the json gem in that any of the options can be set with the opts
28
+ # argument. The json gem limits the opts use to 7 of the options.
29
+ @attrs[:indent] = ''
30
+ @attrs[:space] = ''
31
+ @attrs[:space_before] = ''
32
+ @attrs[:array_nl] = ''
33
+ @attrs[:object_nl] = ''
34
+ @attrs[:allow_nan] = false
35
+ @attrs[:buffer_initial_length] = 1024 # completely ignored by Oj
36
+ @attrs[:depth] = 0
37
+ @attrs[:max_nesting] = 100
38
+ @attrs[:check_circular?] = true
39
+ @attrs[:ascii_only] = false
40
+
41
+ @attrs.merge!(opts)
42
+ end
43
+
44
+ def to_h()
45
+ return @attrs.dup
46
+ end
47
+
48
+ def to_hash()
49
+ return @attrs.dup
50
+ end
51
+
52
+ def allow_nan?()
53
+ @attrs[:allow_nan]
54
+ end
55
+
56
+ def ascii_only?()
57
+ @attrs[:ascii_only]
58
+ end
59
+
60
+ def configure(opts)
61
+ raise TypeError.new('expected a Hash') unless opts.respond_to?(:to_h)
62
+ @attrs.merge!(opts.to_h)
63
+ end
64
+
65
+ def generate(obj)
66
+ JSON.generate(obj)
67
+ end
68
+
69
+ def merge(opts)
70
+ @attrs.merge!(opts)
71
+ end
72
+
73
+ # special rule for this.
74
+ def buffer_initial_length=(len)
75
+ len = 1024 if 0 >= len
76
+ @attrs[:buffer_initial_length] = len
77
+ end
78
+
79
+ # Replaces the Object.respond_to?() method.
80
+ # @param [Symbol] m method symbol
81
+ # @return [Boolean] true for any method that matches an instance
82
+ # variable reader, otherwise false.
83
+ def respond_to?(m)
84
+ return true if super
85
+ return true if has_key?(key)
86
+ return true if has_key?(key.to_s)
87
+ has_key?(key.to_sym)
88
+ end
89
+
90
+ def [](key)
91
+ key = key.to_sym
92
+ @attrs.fetch(key, nil)
93
+ end
94
+
95
+ def []=(key, value)
96
+ key = key.to_sym
97
+ @attrs[key] = value
98
+ end
99
+
100
+ def clear()
101
+ @attrs.clear()
102
+ end
103
+
104
+ def has_key?(k)
105
+ @attrs.has_key?(key.to_sym)
106
+ end
107
+
108
+ # Handles requests for Hash values. Others cause an Exception to be raised.
109
+ # @param [Symbol|String] m method symbol
110
+ # @return [Boolean] the value of the specified instance variable.
111
+ # @raise [ArgumentError] if an argument is given. Zero arguments expected.
112
+ # @raise [NoMethodError] if the instance variable is not defined.
113
+ def method_missing(m, *args, &block)
114
+ if m.to_s.end_with?('=')
115
+ raise ArgumentError.new("wrong number of arguments (#{args.size} for 1 with #{m}) to method #{m}") if args.nil? or 1 != args.length
116
+ m = m.to_s[0..-2]
117
+ m = m.to_sym
118
+ return @attrs.store(m, args[0])
119
+ end
120
+ if @attrs.has_key?(m.to_sym)
121
+ raise ArgumentError.new("wrong number of arguments (#{args.size} for 0 with #{m}) to method #{m}") unless args.nil? or args.empty?
122
+ return @attrs[m.to_sym]
123
+ end
124
+ return @attrs.send(m, *args, &block)
125
+ end
126
+
127
+ end # State
128
+ end # defined check
129
+ end # Generator
130
+ end # Ext
131
+
132
+ end # JSON
data/lib/oj/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Oj
3
- # Current version of the module.
4
- VERSION = '2.18.3'
3
+ # Current version of the module.
4
+ VERSION = '3.13.14'
5
5
  end
data/lib/oj.rb CHANGED
@@ -1,35 +1,5 @@
1
- # Optimized JSON (Oj), as the name implies was written to provide speed
2
- # optimized JSON handling.
3
- #
4
- # Oj has several dump or serialization modes which control how Objects are
5
- # converted to JSON. These modes are set with the :mode option in either the
6
- # default options or as one of the options to the dump() method.
7
- #
8
- # - :strict mode will only allow the 7 basic JSON types to be serialized. Any other Object
9
- # will raise and Exception.
10
- #
11
- # - :null mode replaces any Object that is not one of the JSON types is replaced by a JSON null.
12
- #
13
- # - :object mode will dump any Object as a JSON Object with keys that match
14
- # the Ruby Object's variable names without the '@' character. This is the
15
- # highest performance mode.
16
- #
17
- # - :compat mode is is the compatible with other systems. It will serialize
18
- # any Object but will check to see if the Object implements a to_hash() or
19
- # to_json() method. If either exists that method is used for serializing the
20
- # Object. The to_hash() is more flexible and produces more consistent output
21
- # so it has a preference over the to_json() method. If neither the to_json()
22
- # or to_hash() methods exist then the Oj internal Object variable encoding
23
- # is used.
24
- module Oj
25
- end
26
1
 
27
- begin
28
- # This require exists to get around Rubinius failing to load bigdecimal from
29
- # the C extension.
30
- require 'bigdecimal'
31
- rescue Exception
32
- # ignore
2
+ module Oj
33
3
  end
34
4
 
35
5
  require 'oj/version'
data/pages/Advanced.md ADDED
@@ -0,0 +1,22 @@
1
+ # Advanced Features
2
+
3
+ Optimized JSON (Oj), as the name implies, was written to provide speed optimized
4
+ JSON handling. It was designed as a faster alternative to Yajl and other
5
+ common Ruby JSON parsers. So far it has achieved that, and is about 2 times faster
6
+ than any other Ruby JSON parser, and 3 or more times faster at serializing JSON.
7
+
8
+ Oj has several `dump` or serialization modes which control how Ruby `Object`s are
9
+ converted to JSON. These modes are set with the `:mode` option in either the
10
+ default options or as one of the options to the `dump` method. In addition to
11
+ the various options there are also alternative APIs for parsing JSON.
12
+
13
+ The fastest alternative parser API is the `Oj::Doc` API. The `Oj::Doc` API takes
14
+ a completely different approach by opening a JSON document and providing calls
15
+ to navigate around the JSON while it is open. With this approach, JSON access
16
+ can be well over 20 times faster than conventional JSON parsing.
17
+
18
+ The `Oj::Saj` and `Oj::ScHandler` APIs are callback parsers that
19
+ walk the JSON document depth first and makes callbacks for each element.
20
+ Both callback parser are useful when only portions of the JSON are of
21
+ interest. Performance up to 20 times faster than conventional JSON is
22
+ possible if only a few elements of the JSON are of interest.
@@ -0,0 +1,25 @@
1
+ # Compatibility
2
+
3
+ **Ruby**
4
+
5
+ Oj is compatible with Ruby 2.0.0, 2.1, 2.2, 2.3, 2.4 and RBX.
6
+ Support for JRuby has been removed as JRuby no longer supports C extensions and
7
+ there are bugs in the older versions that are not being fixed.
8
+
9
+ **Rails**
10
+
11
+ Although up until 4.1 Rails uses [multi_json](https://github.com/intridea/multi_json), an [issue in Rails](https://github.com/rails/rails/issues/9212) causes ActiveSupport to fail to make use Oj for JSON handling.
12
+ There is a
13
+ [gem to patch this](https://github.com/GoodLife/rails-patch-json-encode) for
14
+ Rails 3.2 and 4.0. As of the Oj 2.6.0 release the default behavior is to not use
15
+ the `to_json()` method unless the `:use_to_json` option is set. This provides
16
+ another work around to the rails older and newer behavior.
17
+
18
+ The latest ActiveRecord is able to work with Oj by simply using the line:
19
+
20
+ ```
21
+ serialize :metadata, Oj
22
+ ```
23
+
24
+ In version Rails 4.1, multi_json has been removed, and this patch is unnecessary and will no longer work.
25
+ See {file:Rails.md}.
data/pages/Custom.md ADDED
@@ -0,0 +1,23 @@
1
+ # Custom mode
2
+
3
+ The `:custom` mode is the most configurable mode and honors almost all
4
+ options. It provides the most flexibility although it can not be configured to
5
+ be exactly like any of the other modes. Each mode has some special aspect that
6
+ makes it unique. For example, the `:object` mode has it's own unique format
7
+ for object dumping and loading. The `:compat` mode mimic the json gem
8
+ including methods called for encoding and inconsistencies between
9
+ `JSON.dump()`, `JSON.generate()`, and `JSON()`.
10
+
11
+ The `:custom` mode is the default mode. It can be configured either by passing
12
+ options to the `Oj.dump()` and `Oj.load()` methods or by modifying the default
13
+ options.
14
+
15
+ The ability to create objects from JSON object elements is supported and
16
+ considers the `:create_additions` option. Special treatment is given to the
17
+ `:create_id` though. If the `:create_id` is set to `"^o"` then the Oj internal
18
+ encoding and decoding is used. These are more efficient than calling out to a
19
+ `to_json` method or `create_json` method on the classes. Those method do not
20
+ have to exist for the `"^o"` behavior to be utilized. Any other `:create_id`
21
+ value behaves similar to the json gem by calling `to_json` and `create_json`
22
+ as appropriate.
23
+