oj 3.11.0 → 3.16.5

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 (173) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1421 -0
  3. data/README.md +20 -5
  4. data/RELEASE_NOTES.md +61 -0
  5. data/ext/oj/buf.h +48 -38
  6. data/ext/oj/cache.c +329 -0
  7. data/ext/oj/cache.h +22 -0
  8. data/ext/oj/cache8.c +60 -62
  9. data/ext/oj/cache8.h +8 -7
  10. data/ext/oj/circarray.c +35 -35
  11. data/ext/oj/circarray.h +11 -9
  12. data/ext/oj/code.c +156 -174
  13. data/ext/oj/code.h +19 -18
  14. data/ext/oj/compat.c +140 -197
  15. data/ext/oj/custom.c +737 -879
  16. data/ext/oj/debug.c +126 -0
  17. data/ext/oj/dump.c +830 -835
  18. data/ext/oj/dump.h +65 -53
  19. data/ext/oj/dump_compat.c +566 -642
  20. data/ext/oj/dump_leaf.c +95 -182
  21. data/ext/oj/dump_object.c +518 -659
  22. data/ext/oj/dump_strict.c +301 -334
  23. data/ext/oj/encode.h +3 -4
  24. data/ext/oj/encoder.c +43 -0
  25. data/ext/oj/err.c +27 -24
  26. data/ext/oj/err.h +38 -13
  27. data/ext/oj/extconf.rb +23 -7
  28. data/ext/oj/fast.c +1043 -1073
  29. data/ext/oj/intern.c +313 -0
  30. data/ext/oj/intern.h +22 -0
  31. data/ext/oj/mem.c +318 -0
  32. data/ext/oj/mem.h +53 -0
  33. data/ext/oj/mimic_json.c +449 -423
  34. data/ext/oj/object.c +530 -576
  35. data/ext/oj/odd.c +155 -138
  36. data/ext/oj/odd.h +24 -22
  37. data/ext/oj/oj.c +1331 -993
  38. data/ext/oj/oj.h +306 -292
  39. data/ext/oj/parse.c +934 -938
  40. data/ext/oj/parse.h +73 -70
  41. data/ext/oj/parser.c +1600 -0
  42. data/ext/oj/parser.h +101 -0
  43. data/ext/oj/rails.c +795 -845
  44. data/ext/oj/rails.h +7 -7
  45. data/ext/oj/reader.c +132 -140
  46. data/ext/oj/reader.h +67 -78
  47. data/ext/oj/resolve.c +40 -59
  48. data/ext/oj/resolve.h +3 -2
  49. data/ext/oj/rxclass.c +67 -67
  50. data/ext/oj/rxclass.h +11 -9
  51. data/ext/oj/saj.c +441 -480
  52. data/ext/oj/saj2.c +584 -0
  53. data/ext/oj/saj2.h +23 -0
  54. data/ext/oj/scp.c +78 -111
  55. data/ext/oj/sparse.c +726 -730
  56. data/ext/oj/stream_writer.c +146 -165
  57. data/ext/oj/strict.c +103 -123
  58. data/ext/oj/string_writer.c +241 -253
  59. data/ext/oj/trace.c +29 -33
  60. data/ext/oj/trace.h +41 -11
  61. data/ext/oj/usual.c +1218 -0
  62. data/ext/oj/usual.h +69 -0
  63. data/ext/oj/util.c +103 -103
  64. data/ext/oj/util.h +3 -2
  65. data/ext/oj/val_stack.c +60 -49
  66. data/ext/oj/val_stack.h +79 -85
  67. data/ext/oj/validate.c +46 -0
  68. data/ext/oj/wab.c +307 -350
  69. data/lib/oj/active_support_helper.rb +1 -3
  70. data/lib/oj/bag.rb +8 -1
  71. data/lib/oj/easy_hash.rb +9 -9
  72. data/lib/oj/error.rb +1 -2
  73. data/lib/oj/json.rb +162 -150
  74. data/lib/oj/mimic.rb +9 -19
  75. data/lib/oj/saj.rb +20 -6
  76. data/lib/oj/schandler.rb +5 -4
  77. data/lib/oj/state.rb +12 -8
  78. data/lib/oj/version.rb +1 -2
  79. data/lib/oj.rb +2 -0
  80. data/pages/Compatibility.md +1 -1
  81. data/pages/InstallOptions.md +20 -0
  82. data/pages/JsonGem.md +15 -0
  83. data/pages/Modes.md +8 -3
  84. data/pages/Options.md +43 -5
  85. data/pages/Parser.md +309 -0
  86. data/pages/Rails.md +14 -2
  87. data/test/_test_active.rb +8 -9
  88. data/test/_test_active_mimic.rb +7 -8
  89. data/test/_test_mimic_rails.rb +17 -20
  90. data/test/activerecord/result_test.rb +12 -8
  91. data/test/activesupport6/encoding_test.rb +63 -28
  92. data/test/{activesupport5 → activesupport7}/abstract_unit.rb +16 -12
  93. data/test/{activesupport5 → activesupport7}/decoding_test.rb +2 -10
  94. data/test/{activesupport5 → activesupport7}/encoding_test.rb +86 -50
  95. data/test/{activesupport5 → activesupport7}/encoding_test_cases.rb +6 -0
  96. data/test/{activesupport5 → activesupport7}/time_zone_test_helpers.rb +8 -0
  97. data/test/files.rb +15 -15
  98. data/test/foo.rb +17 -43
  99. data/test/helper.rb +16 -3
  100. data/test/isolated/shared.rb +3 -2
  101. data/test/json_gem/json_addition_test.rb +2 -2
  102. data/test/json_gem/json_common_interface_test.rb +8 -6
  103. data/test/json_gem/json_encoding_test.rb +0 -0
  104. data/test/json_gem/json_ext_parser_test.rb +1 -0
  105. data/test/json_gem/json_fixtures_test.rb +3 -2
  106. data/test/json_gem/json_generator_test.rb +71 -41
  107. data/test/json_gem/json_generic_object_test.rb +11 -11
  108. data/test/json_gem/json_parser_test.rb +54 -47
  109. data/test/json_gem/json_string_matching_test.rb +9 -9
  110. data/test/json_gem/test_helper.rb +12 -0
  111. data/test/mem.rb +34 -0
  112. data/test/perf.rb +22 -27
  113. data/test/perf_compat.rb +31 -33
  114. data/test/perf_dump.rb +50 -0
  115. data/test/perf_fast.rb +80 -82
  116. data/test/perf_file.rb +27 -29
  117. data/test/perf_object.rb +65 -69
  118. data/test/perf_once.rb +59 -0
  119. data/test/perf_parser.rb +183 -0
  120. data/test/perf_saj.rb +46 -54
  121. data/test/perf_scp.rb +58 -69
  122. data/test/perf_simple.rb +41 -39
  123. data/test/perf_strict.rb +74 -82
  124. data/test/perf_wab.rb +67 -69
  125. data/test/prec.rb +5 -5
  126. data/test/sample/change.rb +0 -1
  127. data/test/sample/dir.rb +0 -1
  128. data/test/sample/doc.rb +0 -1
  129. data/test/sample/file.rb +0 -1
  130. data/test/sample/group.rb +0 -1
  131. data/test/sample/hasprops.rb +0 -1
  132. data/test/sample/layer.rb +0 -1
  133. data/test/sample/rect.rb +0 -1
  134. data/test/sample/shape.rb +0 -1
  135. data/test/sample/text.rb +0 -1
  136. data/test/sample.rb +16 -16
  137. data/test/sample_json.rb +8 -8
  138. data/test/test_compat.rb +97 -45
  139. data/test/test_custom.rb +73 -51
  140. data/test/test_debian.rb +7 -10
  141. data/test/test_fast.rb +135 -79
  142. data/test/test_file.rb +41 -30
  143. data/test/test_gc.rb +16 -5
  144. data/test/test_generate.rb +21 -0
  145. data/test/test_hash.rb +15 -5
  146. data/test/test_integer_range.rb +9 -9
  147. data/test/test_null.rb +20 -20
  148. data/test/test_object.rb +99 -96
  149. data/test/test_parser.rb +11 -0
  150. data/test/test_parser_debug.rb +27 -0
  151. data/test/test_parser_saj.rb +337 -0
  152. data/test/test_parser_usual.rb +251 -0
  153. data/test/test_rails.rb +2 -2
  154. data/test/test_saj.rb +10 -8
  155. data/test/test_scp.rb +38 -40
  156. data/test/test_strict.rb +40 -32
  157. data/test/test_various.rb +165 -84
  158. data/test/test_wab.rb +48 -44
  159. data/test/test_writer.rb +47 -47
  160. data/test/tests.rb +13 -5
  161. data/test/tests_mimic.rb +12 -3
  162. data/test/tests_mimic_addition.rb +12 -3
  163. metadata +75 -127
  164. data/ext/oj/hash.c +0 -135
  165. data/ext/oj/hash.h +0 -18
  166. data/ext/oj/hash_test.c +0 -484
  167. data/test/activesupport4/decoding_test.rb +0 -108
  168. data/test/activesupport4/encoding_test.rb +0 -531
  169. data/test/activesupport4/test_helper.rb +0 -41
  170. data/test/activesupport5/test_helper.rb +0 -72
  171. data/test/bar.rb +0 -35
  172. data/test/baz.rb +0 -16
  173. data/test/zoo.rb +0 -13
@@ -1,16 +1,14 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  require 'active_support/time'
3
4
 
4
5
  module Oj
5
-
6
6
  # Exists only to handle the ActiveSupport::TimeWithZone.
7
7
  class ActiveSupportHelper
8
-
9
8
  def self.createTimeWithZone(utc, zone)
10
9
  ActiveSupport::TimeWithZone.new(utc - utc.gmt_offset, ActiveSupport::TimeZone[zone])
11
10
  end
12
11
  end
13
-
14
12
  end
15
13
 
16
14
  Oj.register_odd(ActiveSupport::TimeWithZone, Oj::ActiveSupportHelper, :createTimeWithZone, :utc, 'time_zone.name')
data/lib/oj/bag.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module Oj
3
4
 
@@ -14,7 +15,7 @@ module Oj
14
15
  # @example Oj::Bag.new(:@x => 42, :@y => 57)
15
16
  # @param [Hash] args instance variable symbols and their values
16
17
  def initialize(args = {})
17
- args.each do |k,v|
18
+ args.each do |k, v|
18
19
  self.instance_variable_set(k, v)
19
20
  end
20
21
  end
@@ -25,6 +26,7 @@ module Oj
25
26
  # variable reader, otherwise false.
26
27
  def respond_to?(m)
27
28
  return true if super
29
+
28
30
  instance_variables.include?(:"@#{m}")
29
31
  end
30
32
 
@@ -36,8 +38,10 @@ module Oj
36
38
  # @raise [NoMethodError] if the instance variable is not defined.
37
39
  def method_missing(m, *args, &block)
38
40
  raise ArgumentError.new("wrong number of arguments (#{args.size} for 0) to method #{m}") unless args.nil? or args.empty?
41
+
39
42
  at_m = :"@#{m}"
40
43
  raise NoMethodError.new("undefined method #{m}", m) unless instance_variable_defined?(at_m)
44
+
41
45
  instance_variable_get(at_m)
42
46
  end
43
47
 
@@ -46,9 +50,11 @@ module Oj
46
50
  # @return [Boolean] true if each variable and value are the same, otherwise false.
47
51
  def eql?(other)
48
52
  return false if (other.nil? or self.class != other.class)
53
+
49
54
  ova = other.instance_variables
50
55
  iv = instance_variables
51
56
  return false if ova.size != iv.size
57
+
52
58
  iv.all? { |vid| instance_variable_get(vid) != other.instance_variable_get(vid) }
53
59
  end
54
60
  alias == eql?
@@ -64,6 +70,7 @@ module Oj
64
70
  classname = classname.to_s unless classname.is_a?(String)
65
71
  tokens = classname.split('::').map(&:to_sym)
66
72
  raise NameError.new("Invalid classname '#{classname}") if tokens.empty?
73
+
67
74
  m = Object
68
75
  tokens[0..-2].each do |sym|
69
76
  if m.const_defined?(sym)
data/lib/oj/easy_hash.rb CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  module Oj
3
2
 
4
3
  # A Hash subclass that normalizes the hash keys to allow lookup by the
@@ -6,24 +5,23 @@ module Oj
6
5
  # that match the keys.
7
6
  class EasyHash < Hash
8
7
 
9
- # Initializes the instance to an empty Hash.
10
- def initialize()
11
- end
12
-
13
8
  # Replaces the Object.respond_to?() method.
14
9
  # @param [Symbol] m method symbol
10
+ # @param [Boolean] include_all whether to include private and protected methods in the search
15
11
  # @return [Boolean] true for any method that matches an instance
16
12
  # variable reader, otherwise false.
17
- def respond_to?(m)
13
+ def respond_to?(m, include_all = false)
18
14
  return true if super
19
- return true if has_key?(key)
20
- return true if has_key?(key.to_s)
21
- has_key?(key.to_sym)
15
+ return true if has_key?(m)
16
+ return true if has_key?(m.to_s)
17
+
18
+ has_key?(m.to_sym)
22
19
  end
23
20
 
24
21
  def [](key)
25
22
  return fetch(key, nil) if has_key?(key)
26
23
  return fetch(key.to_s, nil) if has_key?(key.to_s)
24
+
27
25
  fetch(key.to_sym, nil)
28
26
  end
29
27
 
@@ -35,9 +33,11 @@ module Oj
35
33
  def method_missing(m, *args, &block)
36
34
  if m.to_s.end_with?('=')
37
35
  raise ArgumentError.new("wrong number of arguments (#{args.size} for 1 with #{m}) to method #{m}") if args.nil? or 1 != args.length
36
+
38
37
  m = m[0..-2]
39
38
  return store(m.to_s, args[0]) if has_key?(m.to_s)
40
39
  return store(m.to_sym, args[0]) if has_key?(m.to_sym)
40
+
41
41
  return store(m, args[0])
42
42
  else
43
43
  raise ArgumentError.new("wrong number of arguments (#{args.size} for 0 with #{m}) to method #{m}") unless args.nil? or args.empty?
data/lib/oj/error.rb CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  module Oj
3
2
 
4
3
  # Inherit Error class from StandardError.
@@ -16,7 +15,7 @@ module Oj
16
15
  # An Exception that is raised if a file fails to load.
17
16
  LoadError = Class.new(Error)
18
17
 
19
- # An Exception that is raised if there is a conflict with mimicing JSON
18
+ # An Exception that is raised if there is a conflict with mimicking JSON
20
19
  MimicError = Class.new(Error)
21
20
 
22
21
  end # Oj
data/lib/oj/json.rb CHANGED
@@ -1,176 +1,188 @@
1
-
2
1
  require 'ostruct'
3
2
  require 'oj/state'
4
3
 
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
4
+ if defined?(JSON::PRETTY_STATE_PROTOTYPE)
5
+ # There are enough people that try to use both the json gen and oj in mimic
6
+ # mode so don't display the warning.
7
+
8
+ # warn "WARNING: oj/json is a compatability shim used by Oj. Requiring the file explicitly is not recommended."
9
+ end
10
+
11
+ unless defined?(JSON::PRETTY_STATE_PROTOTYPE)
12
+ module JSON
13
+ NaN = 0.0/0.0 unless defined?(::JSON::NaN)
14
+ Infinity = 1.0/0.0 unless defined?(::JSON::Infinity)
15
+ MinusInfinity = -1.0/0.0 unless defined?(::JSON::MinusInfinity)
16
+ # Taken from the unit test. Note that items like check_circular? are not
17
+ # present.
18
+ PRETTY_STATE_PROTOTYPE = Ext::Generator::State.from_state({
19
+ :allow_nan => false,
20
+ :array_nl => "\n",
21
+ :ascii_only => false,
22
+ :buffer_initial_length => 1024,
23
+ :depth => 0,
24
+ :indent => " ",
25
+ :max_nesting => 100,
26
+ :object_nl => "\n",
27
+ :space => " ",
28
+ :space_before => "",
29
+ }) unless defined?(::JSON::PRETTY_STATE_PROTOTYPE)
30
+ SAFE_STATE_PROTOTYPE = Ext::Generator::State.from_state({
31
+ :allow_nan => false,
32
+ :array_nl => "",
33
+ :ascii_only => false,
34
+ :buffer_initial_length => 1024,
35
+ :depth => 0,
36
+ :indent => "",
37
+ :max_nesting => 100,
38
+ :object_nl => "",
39
+ :space => "",
40
+ :space_before => "",
41
+ }) unless defined?(::JSON::SAFE_STATE_PROTOTYPE)
42
+ FAST_STATE_PROTOTYPE = Ext::Generator::State.from_state({
43
+ :allow_nan => false,
44
+ :array_nl => "",
45
+ :ascii_only => false,
46
+ :buffer_initial_length => 1024,
47
+ :depth => 0,
48
+ :indent => "",
49
+ :max_nesting => 0,
50
+ :object_nl => "",
51
+ :space => "",
52
+ :space_before => "",
53
+ }) unless defined?(::JSON::FAST_STATE_PROTOTYPE)
54
+
55
+ def self.dump_default_options
56
+ Oj::MimicDumpOption.new
56
57
  end
57
- end
58
58
 
59
- def self.parser=(p)
60
- @@parser = p
61
- end
59
+ def self.dump_default_options=(h)
60
+ m = Oj::MimicDumpOption.new
61
+ h.each do |k, v|
62
+ m[k] = v
63
+ end
64
+ end
62
65
 
63
- def self.parser()
64
- @@parser
65
- end
66
+ def self.parser=(p)
67
+ @@parser = p
68
+ end
66
69
 
67
- def self.generator=(g)
68
- @@generator = g
69
- end
70
+ def self.parser()
71
+ @@parser
72
+ end
70
73
 
71
- def self.generator()
72
- @@generator
73
- end
74
+ def self.generator=(g)
75
+ @@generator = g
76
+ end
74
77
 
75
- module Ext
76
- class Parser
77
- def initialize(src)
78
- raise TypeError.new("already initialized") unless @source.nil?
79
- @source = src
80
- end
78
+ def self.generator()
79
+ @@generator
80
+ end
81
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
82
+ module Ext
83
+ class Parser
84
+ def initialize(src)
85
+ raise TypeError.new("already initialized") unless @source.nil?
114
86
 
115
- attr_writer :json_creatable
87
+ @source = src
88
+ end
116
89
 
117
- def json_create(data)
118
- data = data.dup
119
- data.delete JSON.create_id
120
- self[data]
121
- end
90
+ def source()
91
+ raise TypeError.new("already initialized") if @source.nil?
122
92
 
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
93
+ @source
135
94
  end
136
- end
137
95
 
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
96
+ def parse()
97
+ raise TypeError.new("already initialized") if @source.nil?
142
98
 
143
- def dump(obj, *args)
144
- ::JSON.dump(obj, *args)
145
- end
99
+ JSON.parse(@source)
100
+ end
146
101
 
147
- end # self
102
+ end # Parser
103
+ end # Ext
148
104
 
149
- self.json_creatable = false
105
+ State = ::JSON::Ext::Generator::State unless defined?(::JSON::State)
150
106
 
151
- def to_hash
152
- table
107
+ begin
108
+ send(:remove_const, :Parser)
109
+ rescue
110
+ # ignore and move on
153
111
  end
112
+ Parser = ::JSON::Ext::Parser unless defined?(::JSON::Parser)
113
+ self.parser = ::JSON::Ext::Parser
114
+ self.generator = ::JSON::Ext::Generator
115
+
116
+ # Taken directly from the json gem. Shamelessly copied. It is similar in
117
+ # some ways to the Oj::Bag class or the Oj::EasyHash class.
118
+ class GenericObject < OpenStruct
119
+ class << self
120
+ alias [] new
121
+
122
+ def json_creatable?
123
+ @json_creatable
124
+ end
154
125
 
155
- def [](name)
156
- __send__(name)
157
- end unless method_defined?(:[])
126
+ attr_writer :json_creatable
158
127
 
159
- def []=(name, value)
160
- __send__("#{name}=", value)
161
- end unless method_defined?(:[]=)
128
+ def json_create(data)
129
+ data = data.dup
130
+ data.delete JSON.create_id
131
+ self[data]
132
+ end
162
133
 
163
- def |(other)
164
- self.class[other.to_hash.merge(to_hash)]
165
- end
134
+ def from_hash(object)
135
+ case
136
+ when object.respond_to?(:to_hash)
137
+ result = new
138
+ object.to_hash.each do |key, value|
139
+ result[key] = from_hash(value)
140
+ end
141
+ result
142
+ when object.respond_to?(:to_ary)
143
+ object.to_ary.map { |a| from_hash(a) }
144
+ else
145
+ object
146
+ end
147
+ end
166
148
 
167
- def as_json(*)
168
- { JSON.create_id => self.class.name }.merge to_hash
169
- end
149
+ def load(source, proc = nil, opts = {})
150
+ result = ::JSON.load(source, proc, opts.merge(:object_class => self))
151
+ result.nil? ? new : result
152
+ end
170
153
 
171
- def to_json(*a)
172
- as_json.to_json(*a)
154
+ def dump(obj, *args)
155
+ ::JSON.dump(obj, *args)
156
+ end
157
+
158
+ end # self
159
+
160
+ self.json_creatable = false
161
+
162
+ def to_hash
163
+ table
164
+ end
165
+
166
+ def [](name)
167
+ __send__(name)
168
+ end unless method_defined?(:[])
169
+
170
+ def []=(name, value)
171
+ __send__("#{name}=", value)
172
+ end unless method_defined?(:[]=)
173
+
174
+ def |(other)
175
+ self.class[other.to_hash.merge(to_hash)]
176
+ end
177
+
178
+ def as_json(*)
179
+ { JSON.create_id => self.class.name }.merge to_hash
180
+ end
181
+
182
+ def to_json(*a)
183
+ as_json.to_json(*a)
184
+ end
173
185
  end
174
- end
175
-
176
- end # JSON
186
+
187
+ end # JSON
188
+ end
data/lib/oj/mimic.rb CHANGED
@@ -1,10 +1,7 @@
1
+ # frozen_string_literal: false
1
2
 
2
3
  require 'bigdecimal'
3
- begin
4
- require 'ostruct'
5
- rescue Exception
6
- # ignore
7
- end
4
+ require 'ostruct'
8
5
 
9
6
  module Oj
10
7
 
@@ -23,6 +20,8 @@ module Oj
23
20
  bigdecimal_load: :auto,
24
21
  circular: false,
25
22
  class_cache: false,
23
+ cache_keys: true,
24
+ cache_str: 5,
26
25
  create_additions: false,
27
26
  create_id: "json_class",
28
27
  empty_string: false,
@@ -62,6 +61,8 @@ module Oj
62
61
  self.store(:allow_nan, true)
63
62
  self.store(:quirks_mode, oo[:quirks_mode])
64
63
  self.store(:ascii_only, (:ascii == oo[:escape_mode]))
64
+
65
+ super
65
66
  end
66
67
 
67
68
  def []=(key, value)
@@ -100,6 +101,7 @@ module Oj
100
101
  def as_json(*)
101
102
  name = self.class.name.to_s
102
103
  raise JSON::JSONError, "Only named structs are supported!" if 0 == name.length
104
+
103
105
  { JSON.create_id => name, 't' => table }
104
106
  end
105
107
  end
@@ -133,18 +135,6 @@ module Oj
133
135
  end
134
136
  end
135
137
 
136
- Date.class_eval do
137
- # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
138
- unless defined?(self.as_json)
139
- def as_json(*)
140
- { JSON.create_id => 'Date', 'y' => year, 'm' => month, 'd' => day, 'sg' => start }
141
- end
142
- end
143
- def self.json_create(h)
144
- civil(h['y'], h['m'], h['d'], h['sg'])
145
- end
146
- end
147
-
148
138
  DateTime.class_eval do
149
139
  # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
150
140
  unless defined?(self.as_json)
@@ -242,6 +232,7 @@ module Oj
242
232
  def as_json(*)
243
233
  name = self.class.name.to_s
244
234
  raise JSON::JSONError, "Only named structs are supported!" if 0 == name.length
235
+
245
236
  { JSON.create_id => name, 'v' => values }
246
237
  end
247
238
  end
@@ -273,7 +264,7 @@ module Oj
273
264
  end
274
265
  end
275
266
  def self.json_create(h)
276
- if usec = h.delete('u')
267
+ if (usec = h.delete('u'))
277
268
  h['n'] = usec * 1000
278
269
  end
279
270
  if instance_methods.include?(:tv_nsec)
@@ -283,7 +274,6 @@ module Oj
283
274
  end
284
275
  end
285
276
  end
286
-
287
277
  end # self.mimic_loaded
288
278
 
289
279
  end # Oj
data/lib/oj/saj.rb CHANGED
@@ -1,11 +1,17 @@
1
1
  module Oj
2
- # A SAX style parse handler for JSON hence the acronym SAJ for Simple API for
3
- # JSON. The Oj::Saj handler class should be subclassed and then used with the
4
- # Oj::Saj key_parse() method. The Saj methods will then be called as the file
5
- # is parsed.
2
+ # A SAX style parse handler for JSON hence the acronym SAJ for Simple API
3
+ # for JSON. The Oj::Saj handler class can be subclassed and then used with
4
+ # the Oj::Saj key_parse() method or with the more resent
5
+ # Oj::Parser.new(:saj). The Saj methods will then be called as the file is
6
+ # parsed.
7
+ #
8
+ # With Oj::Parser.new(:saj) each method can also include a line and column
9
+ # argument so hash_start(key) could also be hash_start(key, line,
10
+ # column). The error() method is no used with Oj::Parser.new(:saj) so it
11
+ # will never be called.
6
12
  #
7
13
  # @example
8
- #
14
+ #
9
15
  # require 'oj'
10
16
  #
11
17
  # class MySaj < ::Oj::Saj
@@ -23,6 +29,14 @@ module Oj
23
29
  # Oj.saj_parse(cnt, f)
24
30
  # end
25
31
  #
32
+ # or
33
+ #
34
+ # p = Oj::Parser.new(:saj)
35
+ # p.handler = MySaj.new()
36
+ # File.open('any.json', 'r') do |f|
37
+ # p.parse(f.read)
38
+ # end
39
+ #
26
40
  # To make the desired methods active while parsing the desired method should
27
41
  # be made public in the subclasses. If the methods remain private they will
28
42
  # not be called during parsing.
@@ -61,6 +75,6 @@ module Oj
61
75
 
62
76
  def error(message, line, column)
63
77
  end
64
-
78
+
65
79
  end # Saj
66
80
  end # Oj
data/lib/oj/schandler.rb CHANGED
@@ -64,13 +64,14 @@ module Oj
64
64
  #
65
65
  # hash_end
66
66
  #
67
- # When a hash key is encountered the hash_key method is called with the parsed
68
- # hash value key. The return value from the call is then used as the key in
69
- # the key-value pair that follows.
67
+ # At the end of a JSON object element the hash_end() callback is called if
68
+ # public.
70
69
  #
71
70
  # hash_key
72
71
  #
73
- # At the end of a JSON object element the hash_end() callback is called if public.
72
+ # When a hash key is encountered the hash_key() method is called with the
73
+ # parsed hash value key. The return value from the call is then used as the
74
+ # key in the key-value pair that follows.
74
75
  #
75
76
  # hash_set
76
77
  #