oj 3.13.11 → 3.13.14
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/ext/oj/circarray.c +1 -1
- data/ext/oj/code.c +15 -22
- data/ext/oj/custom.c +28 -55
- data/ext/oj/dump.c +65 -88
- data/ext/oj/dump.h +12 -8
- data/ext/oj/dump_compat.c +43 -80
- data/ext/oj/dump_leaf.c +14 -58
- data/ext/oj/dump_object.c +28 -96
- data/ext/oj/dump_strict.c +12 -24
- data/ext/oj/fast.c +9 -9
- data/ext/oj/intern.c +9 -2
- data/ext/oj/intern.h +1 -1
- data/ext/oj/mimic_json.c +26 -24
- data/ext/oj/odd.c +83 -63
- data/ext/oj/odd.h +13 -13
- data/ext/oj/oj.c +28 -16
- data/ext/oj/oj.h +20 -2
- data/ext/oj/parse.c +3 -2
- data/ext/oj/parser.c +10 -15
- data/ext/oj/rails.c +38 -57
- data/ext/oj/rails.h +1 -1
- data/ext/oj/reader.c +2 -0
- data/ext/oj/saj.c +11 -23
- data/ext/oj/stream_writer.c +3 -1
- data/ext/oj/string_writer.c +12 -5
- data/ext/oj/wab.c +8 -8
- data/lib/oj/version.rb +1 -1
- 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 +1 -8
- data/test/foo.rb +3 -3
- data/test/json_gem/json_generator_test.rb +2 -0
- data/test/perf_dump.rb +50 -0
- data/test/test_object.rb +12 -7
- metadata +15 -17
@@ -0,0 +1,104 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bigdecimal"
|
4
|
+
require "date"
|
5
|
+
require "time"
|
6
|
+
require "pathname"
|
7
|
+
require "uri"
|
8
|
+
|
9
|
+
module JSONTest
|
10
|
+
class Foo
|
11
|
+
def initialize(a, b)
|
12
|
+
@a, @b = a, b
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Hashlike
|
17
|
+
def to_hash
|
18
|
+
{ foo: "hello", bar: "world" }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class Custom
|
23
|
+
def initialize(serialized)
|
24
|
+
@serialized = serialized
|
25
|
+
end
|
26
|
+
|
27
|
+
def as_json(options = nil)
|
28
|
+
@serialized
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
MyStruct = Struct.new(:name, :value) do
|
33
|
+
def initialize(*)
|
34
|
+
@unused = "unused instance variable"
|
35
|
+
super
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
module EncodingTestCases
|
40
|
+
TrueTests = [[ true, %(true) ]]
|
41
|
+
FalseTests = [[ false, %(false) ]]
|
42
|
+
NilTests = [[ nil, %(null) ]]
|
43
|
+
NumericTests = [[ 1, %(1) ],
|
44
|
+
[ 2.5, %(2.5) ],
|
45
|
+
[ 0.0 / 0.0, %(null) ],
|
46
|
+
[ 1.0 / 0.0, %(null) ],
|
47
|
+
[ -1.0 / 0.0, %(null) ],
|
48
|
+
[ BigDecimal("0.0") / BigDecimal("0.0"), %(null) ],
|
49
|
+
[ BigDecimal("2.5"), %("#{BigDecimal('2.5')}") ]]
|
50
|
+
|
51
|
+
StringTests = [[ "this is the <string>", %("this is the \\u003cstring\\u003e")],
|
52
|
+
[ 'a "string" with quotes & an ampersand', %("a \\"string\\" with quotes \\u0026 an ampersand") ],
|
53
|
+
[ "http://test.host/posts/1", %("http://test.host/posts/1")],
|
54
|
+
[ "Control characters: \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\u2028\u2029",
|
55
|
+
%("Control characters: \\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\b\\t\\n\\u000b\\f\\r\\u000e\\u000f\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\\u0018\\u0019\\u001a\\u001b\\u001c\\u001d\\u001e\\u001f\\u2028\\u2029") ]]
|
56
|
+
|
57
|
+
ArrayTests = [[ ["a", "b", "c"], %([\"a\",\"b\",\"c\"]) ],
|
58
|
+
[ [1, "a", :b, nil, false], %([1,\"a\",\"b\",null,false]) ]]
|
59
|
+
|
60
|
+
HashTests = [[ { foo: "bar" }, %({\"foo\":\"bar\"}) ],
|
61
|
+
[ { 1 => 1, 2 => "a", 3 => :b, 4 => nil, 5 => false }, %({\"1\":1,\"2\":\"a\",\"3\":\"b\",\"4\":null,\"5\":false}) ]]
|
62
|
+
|
63
|
+
RangeTests = [[ 1..2, %("1..2")],
|
64
|
+
[ 1...2, %("1...2")],
|
65
|
+
[ 1.5..2.5, %("1.5..2.5")]]
|
66
|
+
|
67
|
+
SymbolTests = [[ :a, %("a") ],
|
68
|
+
[ :this, %("this") ],
|
69
|
+
[ :"a b", %("a b") ]]
|
70
|
+
|
71
|
+
ModuleTests = [[ Module, %("Module") ],
|
72
|
+
[ Class, %("Class") ],
|
73
|
+
[ ActiveSupport, %("ActiveSupport") ],
|
74
|
+
[ ActiveSupport::MessageEncryptor, %("ActiveSupport::MessageEncryptor") ]]
|
75
|
+
ObjectTests = [[ Foo.new(1, 2), %({\"a\":1,\"b\":2}) ]]
|
76
|
+
HashlikeTests = [[ Hashlike.new, %({\"bar\":\"world\",\"foo\":\"hello\"}) ]]
|
77
|
+
StructTests = [[ MyStruct.new(:foo, "bar"), %({\"name\":\"foo\",\"value\":\"bar\"}) ],
|
78
|
+
[ MyStruct.new(nil, nil), %({\"name\":null,\"value\":null}) ]]
|
79
|
+
CustomTests = [[ Custom.new("custom"), '"custom"' ],
|
80
|
+
[ Custom.new(nil), "null" ],
|
81
|
+
[ Custom.new(:a), '"a"' ],
|
82
|
+
[ Custom.new([ :foo, "bar" ]), '["foo","bar"]' ],
|
83
|
+
[ Custom.new(foo: "hello", bar: "world"), '{"bar":"world","foo":"hello"}' ],
|
84
|
+
[ Custom.new(Hashlike.new), '{"bar":"world","foo":"hello"}' ],
|
85
|
+
[ Custom.new(Custom.new(Custom.new(:a))), '"a"' ]]
|
86
|
+
|
87
|
+
RegexpTests = [[ /^a/, '"(?-mix:^a)"' ], [/^\w{1,2}[a-z]+/ix, '"(?ix-m:^\\\\w{1,2}[a-z]+)"']]
|
88
|
+
|
89
|
+
URITests = [[ URI.parse("http://example.com"), %("http://example.com") ]]
|
90
|
+
|
91
|
+
PathnameTests = [[ Pathname.new("lib/index.rb"), %("lib/index.rb") ]]
|
92
|
+
|
93
|
+
IPAddrTests = [[ IPAddr.new("127.0.0.1"), %("127.0.0.1") ]]
|
94
|
+
|
95
|
+
DateTests = [[ Date.new(2005, 2, 1), %("2005/02/01") ]]
|
96
|
+
TimeTests = [[ Time.utc(2005, 2, 1, 15, 15, 10), %("2005/02/01 15:15:10 +0000") ]]
|
97
|
+
DateTimeTests = [[ DateTime.civil(2005, 2, 1, 15, 15, 10), %("2005/02/01 15:15:10 +0000") ]]
|
98
|
+
|
99
|
+
StandardDateTests = [[ Date.new(2005, 2, 1), %("2005-02-01") ]]
|
100
|
+
StandardTimeTests = [[ Time.utc(2005, 2, 1, 15, 15, 10), %("2005-02-01T15:15:10.000Z") ]]
|
101
|
+
StandardDateTimeTests = [[ DateTime.civil(2005, 2, 1, 15, 15, 10), %("2005-02-01T15:15:10.000+00:00") ]]
|
102
|
+
StandardStringTests = [[ "this is the <string>", %("this is the <string>")]]
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TimeZoneTestHelpers
|
4
|
+
def with_tz_default(tz = nil)
|
5
|
+
old_tz = Time.zone
|
6
|
+
Time.zone = tz
|
7
|
+
yield
|
8
|
+
ensure
|
9
|
+
Time.zone = old_tz
|
10
|
+
end
|
11
|
+
|
12
|
+
def with_env_tz(new_tz = "US/Eastern")
|
13
|
+
old_tz, ENV["TZ"] = ENV["TZ"], new_tz
|
14
|
+
yield
|
15
|
+
ensure
|
16
|
+
old_tz ? ENV["TZ"] = old_tz : ENV.delete("TZ")
|
17
|
+
end
|
18
|
+
|
19
|
+
def with_preserve_timezone(value)
|
20
|
+
old_preserve_tz = ActiveSupport.to_time_preserves_timezone
|
21
|
+
ActiveSupport.to_time_preserves_timezone = value
|
22
|
+
yield
|
23
|
+
ensure
|
24
|
+
ActiveSupport.to_time_preserves_timezone = old_preserve_tz
|
25
|
+
end
|
26
|
+
|
27
|
+
def with_tz_mappings(mappings)
|
28
|
+
old_mappings = ActiveSupport::TimeZone::MAPPING.dup
|
29
|
+
ActiveSupport::TimeZone.clear
|
30
|
+
ActiveSupport::TimeZone::MAPPING.clear
|
31
|
+
ActiveSupport::TimeZone::MAPPING.merge!(mappings)
|
32
|
+
|
33
|
+
yield
|
34
|
+
ensure
|
35
|
+
ActiveSupport::TimeZone.clear
|
36
|
+
ActiveSupport::TimeZone::MAPPING.clear
|
37
|
+
ActiveSupport::TimeZone::MAPPING.merge!(old_mappings)
|
38
|
+
end
|
39
|
+
|
40
|
+
def with_utc_to_local_returns_utc_offset_times(value)
|
41
|
+
old_tzinfo2_format = ActiveSupport.utc_to_local_returns_utc_offset_times
|
42
|
+
ActiveSupport.utc_to_local_returns_utc_offset_times = value
|
43
|
+
yield
|
44
|
+
ensure
|
45
|
+
ActiveSupport.utc_to_local_returns_utc_offset_times = old_tzinfo2_format
|
46
|
+
end
|
47
|
+
end
|
data/test/bar.rb
CHANGED
@@ -6,11 +6,4 @@ $: << File.join(File.dirname(__FILE__), "../ext")
|
|
6
6
|
|
7
7
|
require 'oj'
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
p = Oj::Parser.new(:usual)
|
12
|
-
p.cache_keys = false
|
13
|
-
p.symbol_keys = true
|
14
|
-
x = p.parse(json)
|
15
|
-
|
16
|
-
pp x
|
9
|
+
Oj.load(%|{"time":"2021-08-16 12:12:15","a":"5","b":"5"|)
|
data/test/foo.rb
CHANGED
@@ -8,17 +8,15 @@ require "oj"
|
|
8
8
|
require "socket"
|
9
9
|
require 'io/nonblock'
|
10
10
|
|
11
|
-
=begin
|
12
11
|
#pid = spawn("nc -d 0.1 -l 5000", out: "/dev/null")
|
13
12
|
pid = spawn("nc -i 1 -l 7777", out: "/dev/null")
|
14
13
|
at_exit { Process.kill 9, pid }
|
15
14
|
sleep 0.2
|
16
15
|
s = Socket.tcp("localhost", 7777)
|
17
|
-
|
16
|
+
s.nonblock = false
|
18
17
|
1_000_000.times do |x|
|
19
18
|
Oj.to_stream(s, { x: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]})
|
20
19
|
end
|
21
|
-
=end
|
22
20
|
|
23
21
|
=begin
|
24
22
|
IO.pipe do |r, w|
|
@@ -47,6 +45,7 @@ IO.pipe do |r, w|
|
|
47
45
|
end
|
48
46
|
=end
|
49
47
|
|
48
|
+
=begin
|
50
49
|
IO.pipe do |r, w|
|
51
50
|
if fork
|
52
51
|
r.close
|
@@ -75,3 +74,4 @@ IO.pipe do |r, w|
|
|
75
74
|
Process.exit(0)
|
76
75
|
end
|
77
76
|
end
|
77
|
+
=end
|
data/test/perf_dump.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
$: << '.'
|
5
|
+
$: << File.join(File.dirname(__FILE__), "../lib")
|
6
|
+
$: << File.join(File.dirname(__FILE__), "../ext")
|
7
|
+
|
8
|
+
require 'optparse'
|
9
|
+
require 'oj'
|
10
|
+
|
11
|
+
$verbose = false
|
12
|
+
$indent = 2
|
13
|
+
$iter = 100_000
|
14
|
+
$size = 2
|
15
|
+
|
16
|
+
opts = OptionParser.new
|
17
|
+
opts.on("-v", "verbose") { $verbose = true }
|
18
|
+
opts.on("-c", "--count [Int]", Integer, "iterations") { |i| $iter = i }
|
19
|
+
opts.on("-i", "--indent [Int]", Integer, "indentation") { |i| $indent = i }
|
20
|
+
opts.on("-s", "--size [Int]", Integer, "size (~Kbytes)") { |i| $size = i }
|
21
|
+
opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
|
22
|
+
files = opts.parse(ARGV)
|
23
|
+
|
24
|
+
$obj = {
|
25
|
+
'a' => 'Alpha', # string
|
26
|
+
'b' => true, # boolean
|
27
|
+
'c' => 12345, # number
|
28
|
+
'd' => [ true, [false, [-123456789, nil], 3.9676, ['Something else.', false], nil]], # mix it up array
|
29
|
+
'e' => { 'zero' => nil, 'one' => 1, 'two' => 2, 'three' => [3], 'four' => [0, 1, 2, 3, 4] }, # hash
|
30
|
+
'f' => nil, # nil
|
31
|
+
'h' => { 'a' => { 'b' => { 'c' => { 'd' => {'e' => { 'f' => { 'g' => nil }}}}}}}, # deep hash, not that deep
|
32
|
+
'i' => [[[[[[[nil]]]]]]] # deep array, again, not that deep
|
33
|
+
}
|
34
|
+
|
35
|
+
Oj.default_options = { :indent => $indent, :mode => :strict }
|
36
|
+
|
37
|
+
if 0 < $size
|
38
|
+
o = $obj
|
39
|
+
$obj = []
|
40
|
+
(4 * $size).times do
|
41
|
+
$obj << o
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
$json = Oj.dump($obj)
|
46
|
+
GC.start
|
47
|
+
start = Time.now
|
48
|
+
$iter.times { Oj.dump($obj) }
|
49
|
+
duration = Time.now - start
|
50
|
+
puts "Dumped #{$json.length} byte JSON #{$iter} times in %0.3f seconds or %0.3f iteration/sec." % [duration, $iter / duration]
|
data/test/test_object.rb
CHANGED
@@ -221,6 +221,13 @@ class ObjectJuice < Minitest::Test
|
|
221
221
|
|
222
222
|
def teardown
|
223
223
|
Oj.default_options = @default_options
|
224
|
+
#=begin
|
225
|
+
if '3.1.0' <= RUBY_VERSION && !(RbConfig::CONFIG['host_os'] =~ /(mingw|mswin)/)
|
226
|
+
#Oj::debug_odd("teardown before GC.verify_compaction_references")
|
227
|
+
GC.verify_compaction_references(double_heap: true, toward: :empty)
|
228
|
+
#Oj::debug_odd("teardown after GC.verify_compaction_references")
|
229
|
+
end
|
230
|
+
#=end
|
224
231
|
end
|
225
232
|
|
226
233
|
def test_nil
|
@@ -948,6 +955,11 @@ class ObjectJuice < Minitest::Test
|
|
948
955
|
|
949
956
|
def test_odd_date
|
950
957
|
dump_and_load(Date.new(2012, 6, 19), false)
|
958
|
+
|
959
|
+
Oj.register_odd(Date, Date, :jd, :jd)
|
960
|
+
json = Oj.dump(Date.new(2015, 3, 7), :mode => :object)
|
961
|
+
assert_equal(%|{"^O":"Date","jd":2457089}|, json)
|
962
|
+
dump_and_load(Date.new(2012, 6, 19), false)
|
951
963
|
end
|
952
964
|
|
953
965
|
def test_odd_datetime
|
@@ -972,13 +984,6 @@ class ObjectJuice < Minitest::Test
|
|
972
984
|
dump_and_load(s, false)
|
973
985
|
end
|
974
986
|
|
975
|
-
def test_odd_date_replaced
|
976
|
-
Oj.register_odd(Date, Date, :jd, :jd)
|
977
|
-
json = Oj.dump(Date.new(2015, 3, 7), :mode => :object)
|
978
|
-
assert_equal(%|{"^O":"Date","jd":2457089}|, json)
|
979
|
-
dump_and_load(Date.new(2012, 6, 19), false)
|
980
|
-
end
|
981
|
-
|
982
987
|
def test_odd_raw
|
983
988
|
Oj.register_odd_raw(Raw, Raw, :create, :to_json)
|
984
989
|
json = Oj.dump(Raw.new(%|{"a":1}|), :mode => :object)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oj
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.13.
|
4
|
+
version: 3.13.14
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Ohler
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-06-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -58,20 +58,6 @@ dependencies:
|
|
58
58
|
- - "~>"
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: '3.0'
|
61
|
-
- !ruby/object:Gem::Dependency
|
62
|
-
name: wwtd
|
63
|
-
requirement: !ruby/object:Gem::Requirement
|
64
|
-
requirements:
|
65
|
-
- - "~>"
|
66
|
-
- !ruby/object:Gem::Version
|
67
|
-
version: '0'
|
68
|
-
type: :development
|
69
|
-
prerelease: false
|
70
|
-
version_requirements: !ruby/object:Gem::Requirement
|
71
|
-
requirements:
|
72
|
-
- - "~>"
|
73
|
-
- !ruby/object:Gem::Version
|
74
|
-
version: '0'
|
75
61
|
description: The fastest JSON parser and object serializer.
|
76
62
|
email: peter@ohler.com
|
77
63
|
executables: []
|
@@ -200,6 +186,11 @@ files:
|
|
200
186
|
- test/activesupport6/test_common.rb
|
201
187
|
- test/activesupport6/test_helper.rb
|
202
188
|
- test/activesupport6/time_zone_test_helpers.rb
|
189
|
+
- test/activesupport7/abstract_unit.rb
|
190
|
+
- test/activesupport7/decoding_test.rb
|
191
|
+
- test/activesupport7/encoding_test.rb
|
192
|
+
- test/activesupport7/encoding_test_cases.rb
|
193
|
+
- test/activesupport7/time_zone_test_helpers.rb
|
203
194
|
- test/bar.rb
|
204
195
|
- test/baz.rb
|
205
196
|
- test/bug.rb
|
@@ -228,6 +219,7 @@ files:
|
|
228
219
|
- test/mem.rb
|
229
220
|
- test/perf.rb
|
230
221
|
- test/perf_compat.rb
|
222
|
+
- test/perf_dump.rb
|
231
223
|
- test/perf_fast.rb
|
232
224
|
- test/perf_file.rb
|
233
225
|
- test/perf_object.rb
|
@@ -307,7 +299,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
307
299
|
- !ruby/object:Gem::Version
|
308
300
|
version: '0'
|
309
301
|
requirements: []
|
310
|
-
rubygems_version: 3.
|
302
|
+
rubygems_version: 3.3.3
|
311
303
|
signing_key:
|
312
304
|
specification_version: 4
|
313
305
|
summary: A fast JSON parser and serializer.
|
@@ -332,6 +324,11 @@ test_files:
|
|
332
324
|
- test/activesupport6/test_common.rb
|
333
325
|
- test/activesupport6/test_helper.rb
|
334
326
|
- test/activesupport6/time_zone_test_helpers.rb
|
327
|
+
- test/activesupport7/abstract_unit.rb
|
328
|
+
- test/activesupport7/decoding_test.rb
|
329
|
+
- test/activesupport7/encoding_test.rb
|
330
|
+
- test/activesupport7/encoding_test_cases.rb
|
331
|
+
- test/activesupport7/time_zone_test_helpers.rb
|
335
332
|
- test/bar.rb
|
336
333
|
- test/baz.rb
|
337
334
|
- test/bug.rb
|
@@ -360,6 +357,7 @@ test_files:
|
|
360
357
|
- test/mem.rb
|
361
358
|
- test/perf.rb
|
362
359
|
- test/perf_compat.rb
|
360
|
+
- test/perf_dump.rb
|
363
361
|
- test/perf_fast.rb
|
364
362
|
- test/perf_file.rb
|
365
363
|
- test/perf_object.rb
|