oj 2.18.5 → 3.16.11

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 (166) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1452 -0
  3. data/README.md +53 -221
  4. data/RELEASE_NOTES.md +61 -0
  5. data/ext/oj/buf.h +54 -72
  6. data/ext/oj/cache.c +329 -0
  7. data/ext/oj/cache.h +22 -0
  8. data/ext/oj/cache8.c +61 -63
  9. data/ext/oj/cache8.h +12 -39
  10. data/ext/oj/circarray.c +38 -67
  11. data/ext/oj/circarray.h +16 -42
  12. data/ext/oj/code.c +214 -0
  13. data/ext/oj/code.h +40 -0
  14. data/ext/oj/compat.c +194 -110
  15. data/ext/oj/custom.c +1074 -0
  16. data/ext/oj/debug.c +126 -0
  17. data/ext/oj/dump.c +1276 -2494
  18. data/ext/oj/dump.h +110 -0
  19. data/ext/oj/dump_compat.c +897 -0
  20. data/ext/oj/dump_leaf.c +162 -0
  21. data/ext/oj/dump_object.c +710 -0
  22. data/ext/oj/dump_strict.c +399 -0
  23. data/ext/oj/encode.h +7 -42
  24. data/ext/oj/encoder.c +43 -0
  25. data/ext/oj/err.c +28 -53
  26. data/ext/oj/err.h +49 -46
  27. data/ext/oj/extconf.rb +33 -32
  28. data/ext/oj/fast.c +1082 -1098
  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 +919 -0
  34. data/ext/oj/object.c +545 -625
  35. data/ext/oj/odd.c +158 -168
  36. data/ext/oj/odd.h +32 -58
  37. data/ext/oj/oj.c +1727 -2080
  38. data/ext/oj/oj.h +334 -259
  39. data/ext/oj/parse.c +974 -753
  40. data/ext/oj/parse.h +97 -90
  41. data/ext/oj/parser.c +1600 -0
  42. data/ext/oj/parser.h +103 -0
  43. data/ext/oj/rails.c +1478 -0
  44. data/ext/oj/rails.h +18 -0
  45. data/ext/oj/reader.c +136 -163
  46. data/ext/oj/reader.h +76 -112
  47. data/ext/oj/resolve.c +45 -94
  48. data/ext/oj/resolve.h +7 -34
  49. data/ext/oj/rxclass.c +144 -0
  50. data/ext/oj/rxclass.h +26 -0
  51. data/ext/oj/saj.c +445 -511
  52. data/ext/oj/saj2.c +584 -0
  53. data/ext/oj/saj2.h +23 -0
  54. data/ext/oj/scp.c +82 -143
  55. data/ext/oj/simd.h +10 -0
  56. data/ext/oj/sparse.c +749 -644
  57. data/ext/oj/stream_writer.c +329 -0
  58. data/ext/oj/strict.c +114 -112
  59. data/ext/oj/string_writer.c +517 -0
  60. data/ext/oj/trace.c +72 -0
  61. data/ext/oj/trace.h +55 -0
  62. data/ext/oj/usual.c +1218 -0
  63. data/ext/oj/usual.h +69 -0
  64. data/ext/oj/util.c +136 -0
  65. data/ext/oj/util.h +20 -0
  66. data/ext/oj/val_stack.c +75 -72
  67. data/ext/oj/val_stack.h +94 -127
  68. data/ext/oj/validate.c +46 -0
  69. data/ext/oj/wab.c +586 -0
  70. data/lib/oj/active_support_helper.rb +1 -3
  71. data/lib/oj/bag.rb +8 -1
  72. data/lib/oj/easy_hash.rb +21 -13
  73. data/lib/oj/error.rb +10 -12
  74. data/lib/oj/json.rb +188 -0
  75. data/lib/oj/mimic.rb +165 -26
  76. data/lib/oj/saj.rb +20 -6
  77. data/lib/oj/schandler.rb +5 -4
  78. data/lib/oj/state.rb +135 -0
  79. data/lib/oj/version.rb +2 -3
  80. data/lib/oj.rb +3 -31
  81. data/pages/Advanced.md +22 -0
  82. data/pages/Compatibility.md +25 -0
  83. data/pages/Custom.md +23 -0
  84. data/pages/Encoding.md +65 -0
  85. data/pages/InstallOptions.md +20 -0
  86. data/pages/JsonGem.md +94 -0
  87. data/pages/Modes.md +161 -0
  88. data/pages/Options.md +337 -0
  89. data/pages/Parser.md +309 -0
  90. data/pages/Rails.md +167 -0
  91. data/pages/Security.md +20 -0
  92. data/pages/WAB.md +13 -0
  93. metadata +126 -163
  94. data/ext/oj/hash.c +0 -163
  95. data/ext/oj/hash.h +0 -46
  96. data/ext/oj/hash_test.c +0 -512
  97. data/test/_test_active.rb +0 -76
  98. data/test/_test_active_mimic.rb +0 -96
  99. data/test/_test_mimic_rails.rb +0 -126
  100. data/test/activesupport_datetime_test.rb +0 -23
  101. data/test/bug.rb +0 -51
  102. data/test/bug2.rb +0 -10
  103. data/test/bug3.rb +0 -46
  104. data/test/bug_fast.rb +0 -32
  105. data/test/bug_load.rb +0 -24
  106. data/test/crash.rb +0 -111
  107. data/test/curl/curl_oj.rb +0 -46
  108. data/test/curl/get_oj.rb +0 -24
  109. data/test/curl/just_curl.rb +0 -31
  110. data/test/curl/just_oj.rb +0 -51
  111. data/test/example.rb +0 -11
  112. data/test/files.rb +0 -29
  113. data/test/foo.rb +0 -24
  114. data/test/helper.rb +0 -27
  115. data/test/io.rb +0 -48
  116. data/test/isolated/shared.rb +0 -310
  117. data/test/isolated/test_mimic_after.rb +0 -13
  118. data/test/isolated/test_mimic_alone.rb +0 -12
  119. data/test/isolated/test_mimic_as_json.rb +0 -45
  120. data/test/isolated/test_mimic_before.rb +0 -13
  121. data/test/isolated/test_mimic_define.rb +0 -28
  122. data/test/isolated/test_mimic_rails_after.rb +0 -22
  123. data/test/isolated/test_mimic_rails_before.rb +0 -21
  124. data/test/isolated/test_mimic_rails_datetime.rb +0 -27
  125. data/test/isolated/test_mimic_redefine.rb +0 -15
  126. data/test/mod.rb +0 -16
  127. data/test/perf.rb +0 -107
  128. data/test/perf_compat.rb +0 -128
  129. data/test/perf_fast.rb +0 -164
  130. data/test/perf_file.rb +0 -64
  131. data/test/perf_object.rb +0 -138
  132. data/test/perf_saj.rb +0 -109
  133. data/test/perf_scp.rb +0 -151
  134. data/test/perf_simple.rb +0 -287
  135. data/test/perf_strict.rb +0 -128
  136. data/test/rails.rb +0 -50
  137. data/test/russian.rb +0 -18
  138. data/test/sample/change.rb +0 -14
  139. data/test/sample/dir.rb +0 -19
  140. data/test/sample/doc.rb +0 -36
  141. data/test/sample/file.rb +0 -48
  142. data/test/sample/group.rb +0 -16
  143. data/test/sample/hasprops.rb +0 -16
  144. data/test/sample/layer.rb +0 -12
  145. data/test/sample/line.rb +0 -20
  146. data/test/sample/oval.rb +0 -10
  147. data/test/sample/rect.rb +0 -10
  148. data/test/sample/shape.rb +0 -35
  149. data/test/sample/text.rb +0 -20
  150. data/test/sample.rb +0 -55
  151. data/test/sample_json.rb +0 -37
  152. data/test/struct.rb +0 -29
  153. data/test/test_compat.rb +0 -398
  154. data/test/test_debian.rb +0 -53
  155. data/test/test_fast.rb +0 -458
  156. data/test/test_file.rb +0 -245
  157. data/test/test_gc.rb +0 -49
  158. data/test/test_hash.rb +0 -29
  159. data/test/test_object.rb +0 -745
  160. data/test/test_saj.rb +0 -186
  161. data/test/test_scp.rb +0 -396
  162. data/test/test_serializer.rb +0 -59
  163. data/test/test_strict.rb +0 -254
  164. data/test/test_various.rb +0 -1383
  165. data/test/test_writer.rb +0 -308
  166. data/test/write_timebars.rb +0 -31
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
 
@@ -33,10 +31,20 @@ module Oj
33
31
  # @raise [ArgumentError] if an argument is given. Zero arguments expected.
34
32
  # @raise [NoMethodError] if the instance variable is not defined.
35
33
  def method_missing(m, *args, &block)
36
- raise ArgumentError.new("wrong number of arguments (#{args.size} for 0 with #{m}) to method #{m}") unless args.nil? or args.empty?
37
- return fetch(m, nil) if has_key?(m)
38
- return fetch(m.to_s, nil) if has_key?(m.to_s)
39
- return fetch(m.to_sym, nil) if has_key?(m.to_sym)
34
+ if m.to_s.end_with?('=')
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
+
37
+ m = m[0..-2]
38
+ return store(m.to_s, args[0]) if has_key?(m.to_s)
39
+ return store(m.to_sym, args[0]) if has_key?(m.to_sym)
40
+
41
+ return store(m, args[0])
42
+ else
43
+ raise ArgumentError.new("wrong number of arguments (#{args.size} for 0 with #{m}) to method #{m}") unless args.nil? or args.empty?
44
+ return fetch(m, nil) if has_key?(m)
45
+ return fetch(m.to_s, nil) if has_key?(m.to_s)
46
+ return fetch(m.to_sym, nil) if has_key?(m.to_sym)
47
+ end
40
48
  raise NoMethodError.new("undefined method #{m}", m)
41
49
  end
42
50
 
data/lib/oj/error.rb CHANGED
@@ -1,23 +1,21 @@
1
-
2
1
  module Oj
3
2
 
4
- class Error < StandardError
5
- end # Error
3
+ # Inherit Error class from StandardError.
4
+ Error = Class.new(StandardError)
5
+
6
+ # Following classes inherit from the Error class.
7
+ # -----------------------------------------------
6
8
 
7
9
  # An Exception that is raised as a result of a parse error while parsing a JSON document.
8
- class ParseError < Error
9
- end # ParseError
10
+ ParseError = Class.new(Error)
10
11
 
11
12
  # An Exception that is raised as a result of a path being too deep.
12
- class DepthError < Error
13
- end # DepthError
13
+ DepthError = Class.new(Error)
14
14
 
15
15
  # An Exception that is raised if a file fails to load.
16
- class LoadError < Error
17
- end # LoadError
16
+ LoadError = Class.new(Error)
18
17
 
19
- # An Exception that is raised if there is a conflict with mimicing JSON
20
- class MimicError < Error
21
- end # MimicError
18
+ # An Exception that is raised if there is a conflict with mimicking JSON
19
+ MimicError = Class.new(Error)
22
20
 
23
21
  end # Oj
data/lib/oj/json.rb ADDED
@@ -0,0 +1,188 @@
1
+ require 'ostruct'
2
+ require 'oj/state'
3
+
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
57
+ end
58
+
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
65
+
66
+ def self.parser=(p)
67
+ @@parser = p
68
+ end
69
+
70
+ def self.parser()
71
+ @@parser
72
+ end
73
+
74
+ def self.generator=(g)
75
+ @@generator = g
76
+ end
77
+
78
+ def self.generator()
79
+ @@generator
80
+ end
81
+
82
+ module Ext
83
+ class Parser
84
+ def initialize(src)
85
+ raise TypeError.new("already initialized") unless @source.nil?
86
+
87
+ @source = src
88
+ end
89
+
90
+ def source()
91
+ raise TypeError.new("already initialized") if @source.nil?
92
+
93
+ @source
94
+ end
95
+
96
+ def parse()
97
+ raise TypeError.new("already initialized") if @source.nil?
98
+
99
+ JSON.parse(@source)
100
+ end
101
+
102
+ end # Parser
103
+ end # Ext
104
+
105
+ State = ::JSON::Ext::Generator::State unless defined?(::JSON::State)
106
+
107
+ begin
108
+ send(:remove_const, :Parser)
109
+ rescue
110
+ # ignore and move on
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
125
+
126
+ attr_writer :json_creatable
127
+
128
+ def json_create(data)
129
+ data = data.dup
130
+ data.delete JSON.create_id
131
+ self[data]
132
+ end
133
+
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
148
+
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
153
+
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
185
+ end
186
+
187
+ end # JSON
188
+ end
data/lib/oj/mimic.rb CHANGED
@@ -1,12 +1,56 @@
1
+ # frozen_string_literal: false
1
2
 
2
- begin
3
- require 'ostruct'
4
- rescue Exception
5
- # ignore
6
- end
3
+ require 'bigdecimal'
4
+ require 'ostruct'
7
5
 
8
6
  module Oj
9
7
 
8
+ ##
9
+ # Custom mode can be used to emulate the compat mode with some minor
10
+ # differences. These are the options that setup the custom mode to be like
11
+ # the compat mode.
12
+ CUSTOM_MIMIC_JSON_OPTIONS = {
13
+ allow_gc: true,
14
+ allow_invalid_unicode: false,
15
+ allow_nan: false,
16
+ array_class: nil,
17
+ array_nl: nil,
18
+ auto_define: false,
19
+ bigdecimal_as_decimal: false,
20
+ bigdecimal_load: :auto,
21
+ circular: false,
22
+ class_cache: false,
23
+ cache_keys: true,
24
+ cache_str: 5,
25
+ create_additions: false,
26
+ create_id: "json_class",
27
+ empty_string: false,
28
+ escape_mode: :unicode_xss,
29
+ float_precision: 0,
30
+ hash_class: nil,
31
+ ignore: nil,
32
+ ignore_under: false,
33
+ indent: 0,
34
+ integer_range: nil,
35
+ mode: :custom,
36
+ nan: :raise,
37
+ nilnil: false,
38
+ object_nl: nil,
39
+ omit_nil: false,
40
+ quirks_mode: true,
41
+ safe: false,
42
+ second_precision: 3,
43
+ space: nil,
44
+ space_before: nil,
45
+ symbol_keys: false,
46
+ time_format: :ruby,
47
+ trace: false,
48
+ use_as_json: false,
49
+ use_raw_json: false,
50
+ use_to_hash: false,
51
+ use_to_json: true,
52
+ }
53
+
10
54
  # A bit hack-ish but does the trick. The JSON.dump_default_options is a Hash
11
55
  # but in mimic we use a C struct to store defaults. This class creates a view
12
56
  # onto that struct.
@@ -17,6 +61,8 @@ module Oj
17
61
  self.store(:allow_nan, true)
18
62
  self.store(:quirks_mode, oo[:quirks_mode])
19
63
  self.store(:ascii_only, (:ascii == oo[:escape_mode]))
64
+
65
+ super
20
66
  end
21
67
 
22
68
  def []=(key, value)
@@ -29,20 +75,25 @@ module Oj
29
75
  end
30
76
  end
31
77
 
78
+ # Loads mimic-ed JSON paths. Used by Oj.mimic_JSON().
79
+ # @param mimic_paths [Array] additional paths to add to the Ruby loaded features.
32
80
  def self.mimic_loaded(mimic_paths=[])
33
81
  $LOAD_PATH.each do |d|
34
82
  next unless File.exist?(d)
35
83
 
36
84
  jfile = File.join(d, 'json.rb')
37
85
  $LOADED_FEATURES << jfile unless $LOADED_FEATURES.include?(jfile) if File.exist?(jfile)
38
-
86
+
39
87
  Dir.glob(File.join(d, 'json', '**', '*.rb')).each do |file|
40
- $LOADED_FEATURES << file unless $LOADED_FEATURES.include?(file)
88
+ # allow json/add/xxx to be loaded. User can override with Oj.add_to_json(xxx).
89
+ $LOADED_FEATURES << file unless $LOADED_FEATURES.include?(file) unless file.include?('add')
41
90
  end
42
91
  end
43
92
  mimic_paths.each { |p| $LOADED_FEATURES << p }
44
93
  $LOADED_FEATURES << 'json' unless $LOADED_FEATURES.include?('json')
45
94
 
95
+ require 'oj/json'
96
+
46
97
  if Object.const_defined?('OpenStruct')
47
98
  OpenStruct.class_eval do
48
99
  # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
@@ -50,13 +101,93 @@ module Oj
50
101
  def as_json(*)
51
102
  name = self.class.name.to_s
52
103
  raise JSON::JSONError, "Only named structs are supported!" if 0 == name.length
104
+
53
105
  { JSON.create_id => name, 't' => table }
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)
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 }
58
184
  end
59
185
  end
186
+ def self.json_create(h)
187
+ e = new(h['m'])
188
+ e.set_backtrace(h['b'])
189
+ e
190
+ end
60
191
  end
61
192
 
62
193
  Range.class_eval do
@@ -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
 
@@ -101,11 +232,12 @@ module Oj
101
232
  def as_json(*)
102
233
  name = self.class.name.to_s
103
234
  raise JSON::JSONError, "Only named structs are supported!" if 0 == name.length
235
+
104
236
  { JSON.create_id => name, 'v' => values }
105
237
  end
106
238
  end
107
239
  def self.json_create(h)
108
- new(h['v'])
240
+ new(*h['v'])
109
241
  end
110
242
  end
111
243
 
@@ -125,7 +257,6 @@ module Oj
125
257
  # Both the JSON gem and Rails monkey patch as_json. Let them battle it out.
126
258
  unless defined?(self.as_json)
127
259
  def as_json(*)
128
- {JSON.create_id => 'Symbol', 's' => to_s }
129
260
  nsecs = [ tv_usec * 1000 ]
130
261
  nsecs << tv_nsec if respond_to?(:tv_nsec)
131
262
  nsecs = nsecs.max
@@ -133,7 +264,7 @@ module Oj
133
264
  end
134
265
  end
135
266
  def self.json_create(h)
136
- if usec = h.delete('u')
267
+ if (usec = h.delete('u'))
137
268
  h['n'] = usec * 1000
138
269
  end
139
270
  if instance_methods.include?(:tv_nsec)
@@ -143,20 +274,28 @@ module Oj
143
274
  end
144
275
  end
145
276
  end
146
-
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/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
  #