oj 2.18.3 → 3.13.14
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +1324 -0
- data/README.md +51 -204
- data/RELEASE_NOTES.md +61 -0
- data/ext/oj/buf.h +49 -72
- data/ext/oj/cache.c +326 -0
- data/ext/oj/cache.h +21 -0
- data/ext/oj/cache8.c +61 -64
- data/ext/oj/cache8.h +12 -39
- data/ext/oj/circarray.c +37 -68
- data/ext/oj/circarray.h +16 -42
- data/ext/oj/code.c +221 -0
- data/ext/oj/code.h +40 -0
- data/ext/oj/compat.c +231 -107
- data/ext/oj/custom.c +1125 -0
- data/ext/oj/debug.c +132 -0
- data/ext/oj/dump.c +935 -2513
- data/ext/oj/dump.h +108 -0
- data/ext/oj/dump_compat.c +936 -0
- data/ext/oj/dump_leaf.c +164 -0
- data/ext/oj/dump_object.c +761 -0
- data/ext/oj/dump_strict.c +410 -0
- data/ext/oj/encode.h +7 -42
- data/ext/oj/encoder.c +43 -0
- data/ext/oj/err.c +40 -54
- data/ext/oj/err.h +52 -46
- data/ext/oj/extconf.rb +21 -30
- data/ext/oj/fast.c +1097 -1080
- data/ext/oj/intern.c +301 -0
- data/ext/oj/intern.h +26 -0
- data/ext/oj/mimic_json.c +893 -0
- data/ext/oj/object.c +549 -620
- data/ext/oj/odd.c +155 -167
- data/ext/oj/odd.h +37 -63
- data/ext/oj/oj.c +1661 -2063
- data/ext/oj/oj.h +341 -270
- data/ext/oj/parse.c +974 -737
- data/ext/oj/parse.h +105 -97
- data/ext/oj/parser.c +1526 -0
- data/ext/oj/parser.h +90 -0
- data/ext/oj/rails.c +1504 -0
- data/ext/oj/rails.h +18 -0
- data/ext/oj/reader.c +141 -163
- data/ext/oj/reader.h +75 -113
- data/ext/oj/resolve.c +45 -93
- data/ext/oj/resolve.h +7 -34
- data/ext/oj/rxclass.c +143 -0
- data/ext/oj/rxclass.h +26 -0
- data/ext/oj/saj.c +447 -511
- data/ext/oj/saj2.c +348 -0
- data/ext/oj/scp.c +91 -138
- data/ext/oj/sparse.c +793 -644
- data/ext/oj/stream_writer.c +331 -0
- data/ext/oj/strict.c +145 -109
- data/ext/oj/string_writer.c +493 -0
- data/ext/oj/trace.c +72 -0
- data/ext/oj/trace.h +28 -0
- data/ext/oj/usual.c +1254 -0
- data/ext/oj/util.c +136 -0
- data/ext/oj/util.h +20 -0
- data/ext/oj/val_stack.c +62 -70
- data/ext/oj/val_stack.h +95 -129
- data/ext/oj/validate.c +51 -0
- data/ext/oj/wab.c +622 -0
- data/lib/oj/bag.rb +1 -0
- data/lib/oj/easy_hash.rb +17 -8
- data/lib/oj/error.rb +10 -11
- data/lib/oj/json.rb +176 -0
- data/lib/oj/mimic.rb +158 -19
- data/lib/oj/state.rb +132 -0
- data/lib/oj/version.rb +2 -2
- data/lib/oj.rb +1 -31
- data/pages/Advanced.md +22 -0
- data/pages/Compatibility.md +25 -0
- data/pages/Custom.md +23 -0
- data/pages/Encoding.md +65 -0
- data/pages/JsonGem.md +94 -0
- data/pages/Modes.md +161 -0
- data/pages/Options.md +327 -0
- data/pages/Parser.md +309 -0
- data/pages/Rails.md +167 -0
- data/pages/Security.md +20 -0
- data/pages/WAB.md +13 -0
- data/test/activerecord/result_test.rb +32 -0
- data/test/activesupport4/decoding_test.rb +108 -0
- data/test/activesupport4/encoding_test.rb +531 -0
- data/test/activesupport4/test_helper.rb +41 -0
- data/test/activesupport5/abstract_unit.rb +45 -0
- data/test/activesupport5/decoding_test.rb +133 -0
- data/test/activesupport5/encoding_test.rb +500 -0
- data/test/activesupport5/encoding_test_cases.rb +98 -0
- data/test/activesupport5/test_helper.rb +72 -0
- data/test/activesupport5/time_zone_test_helpers.rb +39 -0
- data/test/activesupport6/abstract_unit.rb +44 -0
- data/test/activesupport6/decoding_test.rb +133 -0
- data/test/activesupport6/encoding_test.rb +507 -0
- data/test/activesupport6/encoding_test_cases.rb +98 -0
- data/test/activesupport6/test_common.rb +17 -0
- data/test/activesupport6/test_helper.rb +163 -0
- data/test/activesupport6/time_zone_test_helpers.rb +39 -0
- data/test/activesupport7/abstract_unit.rb +49 -0
- data/test/activesupport7/decoding_test.rb +125 -0
- data/test/activesupport7/encoding_test.rb +486 -0
- data/test/activesupport7/encoding_test_cases.rb +104 -0
- data/test/activesupport7/time_zone_test_helpers.rb +47 -0
- data/test/bar.rb +9 -0
- data/test/baz.rb +16 -0
- data/test/bug.rb +11 -46
- data/test/foo.rb +69 -16
- data/test/helper.rb +10 -1
- data/test/isolated/shared.rb +12 -8
- data/test/isolated/test_mimic_rails_after.rb +3 -3
- data/test/isolated/test_mimic_rails_before.rb +3 -3
- data/test/json_gem/json_addition_test.rb +216 -0
- data/test/json_gem/json_common_interface_test.rb +153 -0
- data/test/json_gem/json_encoding_test.rb +107 -0
- data/test/json_gem/json_ext_parser_test.rb +20 -0
- data/test/json_gem/json_fixtures_test.rb +35 -0
- data/test/json_gem/json_generator_test.rb +397 -0
- data/test/json_gem/json_generic_object_test.rb +90 -0
- data/test/json_gem/json_parser_test.rb +470 -0
- data/test/json_gem/json_string_matching_test.rb +42 -0
- data/test/json_gem/test_helper.rb +26 -0
- data/test/mem.rb +33 -0
- data/test/perf.rb +1 -1
- data/test/perf_compat.rb +30 -28
- data/test/perf_dump.rb +50 -0
- data/test/perf_object.rb +1 -1
- data/test/perf_once.rb +58 -0
- data/test/perf_parser.rb +189 -0
- data/test/perf_scp.rb +11 -10
- data/test/perf_strict.rb +30 -19
- data/test/perf_wab.rb +131 -0
- data/test/prec.rb +23 -0
- data/test/sample.rb +0 -1
- data/test/sample_json.rb +1 -1
- data/test/test_compat.rb +219 -102
- data/test/test_custom.rb +533 -0
- data/test/test_fast.rb +107 -35
- data/test/test_file.rb +19 -25
- data/test/test_generate.rb +21 -0
- data/test/test_hash.rb +11 -1
- data/test/test_integer_range.rb +72 -0
- data/test/test_null.rb +376 -0
- data/test/test_object.rb +357 -70
- data/test/test_parser.rb +27 -0
- data/test/test_parser_saj.rb +245 -0
- data/test/test_parser_usual.rb +217 -0
- data/test/test_rails.rb +35 -0
- data/test/test_saj.rb +1 -1
- data/test/test_scp.rb +39 -2
- data/test/test_strict.rb +186 -7
- data/test/test_various.rb +160 -774
- data/test/test_wab.rb +307 -0
- data/test/test_writer.rb +90 -2
- data/test/tests.rb +24 -0
- data/test/tests_mimic.rb +14 -0
- data/test/tests_mimic_addition.rb +7 -0
- data/test/zoo.rb +13 -0
- metadata +194 -56
- data/ext/oj/hash.c +0 -163
- data/ext/oj/hash.h +0 -46
- data/ext/oj/hash_test.c +0 -512
- data/test/activesupport_datetime_test.rb +0 -23
- data/test/bug2.rb +0 -10
- data/test/bug3.rb +0 -46
- data/test/bug_fast.rb +0 -32
- data/test/bug_load.rb +0 -24
- data/test/crash.rb +0 -111
- data/test/curl/curl_oj.rb +0 -46
- data/test/curl/get_oj.rb +0 -24
- data/test/curl/just_curl.rb +0 -31
- data/test/curl/just_oj.rb +0 -51
- data/test/example.rb +0 -11
- data/test/io.rb +0 -48
- data/test/isolated/test_mimic_rails_datetime.rb +0 -27
- data/test/mod.rb +0 -16
- data/test/rails.rb +0 -50
- data/test/russian.rb +0 -18
- data/test/struct.rb +0 -29
- data/test/test_serializer.rb +0 -59
- 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
|
-
|
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
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
|
-
|
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
|
+
|