oj 3.13.11 → 3.13.14
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.
- 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
|