oj 3.8.0 → 3.10.0
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/README.md +2 -2
- data/ext/oj/custom.c +61 -36
- data/ext/oj/dump.c +9 -12
- data/ext/oj/dump_compat.c +6 -9
- data/ext/oj/dump_object.c +14 -9
- data/ext/oj/extconf.rb +1 -0
- data/ext/oj/mimic_json.c +4 -2
- data/ext/oj/object.c +8 -5
- data/ext/oj/oj.c +47 -30
- data/ext/oj/oj.h +6 -4
- data/ext/oj/parse.c +15 -2
- data/ext/oj/parse.h +1 -0
- data/ext/oj/rails.c +9 -2
- data/ext/oj/resolve.c +3 -3
- data/ext/oj/sparse.c +4 -0
- data/ext/oj/util.c +5 -5
- data/ext/oj/val_stack.c +9 -9
- data/ext/oj/val_stack.h +9 -9
- data/lib/oj/json.rb +1 -1
- data/lib/oj/version.rb +1 -1
- data/pages/Options.md +4 -0
- data/pages/Rails.md +21 -21
- data/test/activesupport5/abstract_unit.rb +45 -0
- data/test/activesupport5/decoding_test.rb +68 -60
- data/test/activesupport5/encoding_test.rb +111 -96
- data/test/activesupport5/encoding_test_cases.rb +33 -25
- data/test/activesupport5/test_helper.rb +43 -21
- data/test/activesupport5/time_zone_test_helpers.rb +18 -3
- 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/bar.rb +8 -11
- data/test/baz.rb +16 -0
- data/test/test_compat.rb +0 -7
- data/test/test_custom.rb +6 -2
- data/test/test_integer_range.rb +1 -2
- data/test/test_object.rb +4 -3
- data/test/test_strict.rb +24 -1
- data/test/test_various.rb +41 -62
- metadata +20 -2
@@ -1,7 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "abstract_unit"
|
4
|
+
require "active_support/json"
|
5
|
+
require "active_support/time"
|
6
|
+
require_relative "time_zone_test_helpers"
|
5
7
|
|
6
8
|
require 'oj'
|
7
9
|
|
@@ -10,6 +12,11 @@ Oj::Rails.set_decoder()
|
|
10
12
|
class TestJSONDecoding < ActiveSupport::TestCase
|
11
13
|
include TimeZoneTestHelpers
|
12
14
|
|
15
|
+
# Added for testing if Oj is used.
|
16
|
+
test "oj is used as an encoder" do
|
17
|
+
assert_equal ActiveSupport.json_encoder, Oj::Rails::Encoder
|
18
|
+
end
|
19
|
+
|
13
20
|
class Foo
|
14
21
|
def self.json_create(object)
|
15
22
|
"Foo"
|
@@ -17,76 +24,78 @@ class TestJSONDecoding < ActiveSupport::TestCase
|
|
17
24
|
end
|
18
25
|
|
19
26
|
TESTS = {
|
20
|
-
%q({"returnTo":{"\/categories":"\/"}}) => {"returnTo" => {"/categories" => "/"}},
|
21
|
-
%q({"return\\"To\\":":{"\/categories":"\/"}}) => {"return\"To\":" => {"/categories" => "/"}},
|
22
|
-
%q({"returnTo":{"\/categories":1}})
|
23
|
-
%({"returnTo":[1,"a"]}) => {"returnTo" => [1, "a"]},
|
24
|
-
%({"returnTo":[1,"\\"a\\",", "b"]}) => {"returnTo" => [1, "\"a\",", "b"]},
|
25
|
-
%({"a": "'", "b": "5,000"}) => {"a" => "'", "b" => "5,000"},
|
26
|
-
%({"a": "a's, b's and c's", "b": "5,000"}) => {"a" => "a's, b's and c's", "b" => "5,000"},
|
27
|
+
%q({"returnTo":{"\/categories":"\/"}}) => { "returnTo" => { "/categories" => "/" } },
|
28
|
+
%q({"return\\"To\\":":{"\/categories":"\/"}}) => { "return\"To\":" => { "/categories" => "/" } },
|
29
|
+
%q({"returnTo":{"\/categories":1}}) => { "returnTo" => { "/categories" => 1 } },
|
30
|
+
%({"returnTo":[1,"a"]}) => { "returnTo" => [1, "a"] },
|
31
|
+
%({"returnTo":[1,"\\"a\\",", "b"]}) => { "returnTo" => [1, "\"a\",", "b"] },
|
32
|
+
%({"a": "'", "b": "5,000"}) => { "a" => "'", "b" => "5,000" },
|
33
|
+
%({"a": "a's, b's and c's", "b": "5,000"}) => { "a" => "a's, b's and c's", "b" => "5,000" },
|
27
34
|
# multibyte
|
28
|
-
%({"matzue": "松江", "asakusa": "浅草"}) => {"matzue" => "松江", "asakusa" => "浅草"},
|
29
|
-
%({"a": "2007-01-01"}) => {
|
30
|
-
%({"a": "2007-01-01 01:12:34 Z"}) => {
|
35
|
+
%({"matzue": "松江", "asakusa": "浅草"}) => { "matzue" => "松江", "asakusa" => "浅草" },
|
36
|
+
%({"a": "2007-01-01"}) => { "a" => Date.new(2007, 1, 1) },
|
37
|
+
%({"a": "2007-01-01 01:12:34 Z"}) => { "a" => Time.utc(2007, 1, 1, 1, 12, 34) },
|
31
38
|
%(["2007-01-01 01:12:34 Z"]) => [Time.utc(2007, 1, 1, 1, 12, 34)],
|
32
39
|
%(["2007-01-01 01:12:34 Z", "2007-01-01 01:12:35 Z"]) => [Time.utc(2007, 1, 1, 1, 12, 34), Time.utc(2007, 1, 1, 1, 12, 35)],
|
33
40
|
# no time zone
|
34
|
-
%({"a": "2007-01-01 01:12:34"}) => {
|
41
|
+
%({"a": "2007-01-01 01:12:34"}) => { "a" => Time.new(2007, 1, 1, 1, 12, 34, "-05:00") },
|
35
42
|
# invalid date
|
36
|
-
%({"a": "1089-10-40"}) => {
|
43
|
+
%({"a": "1089-10-40"}) => { "a" => "1089-10-40" },
|
37
44
|
# xmlschema date notation
|
38
|
-
%({"a": "2009-08-10T19:01:02"}) => {
|
39
|
-
%({"a": "2009-08-10T19:01:02Z"}) => {
|
40
|
-
%({"a": "2009-08-10T19:01:02+02:00"}) => {
|
41
|
-
%({"a": "2009-08-10T19:01:02-05:00"}) => {
|
45
|
+
%({"a": "2009-08-10T19:01:02"}) => { "a" => Time.new(2009, 8, 10, 19, 1, 2, "-04:00") },
|
46
|
+
%({"a": "2009-08-10T19:01:02Z"}) => { "a" => Time.utc(2009, 8, 10, 19, 1, 2) },
|
47
|
+
%({"a": "2009-08-10T19:01:02+02:00"}) => { "a" => Time.utc(2009, 8, 10, 17, 1, 2) },
|
48
|
+
%({"a": "2009-08-10T19:01:02-05:00"}) => { "a" => Time.utc(2009, 8, 11, 00, 1, 2) },
|
42
49
|
# needs to be *exact*
|
43
|
-
%({"a": " 2007-01-01 01:12:34 Z "}) => {
|
44
|
-
%({"a": "2007-01-01 : it's your birthday"}) => {
|
50
|
+
%({"a": " 2007-01-01 01:12:34 Z "}) => { "a" => " 2007-01-01 01:12:34 Z " },
|
51
|
+
%({"a": "2007-01-01 : it's your birthday"}) => { "a" => "2007-01-01 : it's your birthday" },
|
45
52
|
%([]) => [],
|
46
53
|
%({}) => {},
|
47
|
-
%({"a":1})
|
48
|
-
%({"a": ""})
|
49
|
-
%({"a":"\\""}) => {"a" => "\""},
|
50
|
-
%({"a": null}) => {"a" => nil},
|
51
|
-
%({"a": true}) => {"a" => true},
|
52
|
-
%({"a": false}) => {"a" => false},
|
53
|
-
|
54
|
-
%q({"a": "http:\/\/test.host\/posts\/1"}) => {"a" => "http://test.host/posts/1"},
|
55
|
-
%q({"a": "\u003cunicode\u0020escape\u003e"}) => {"a" => "<unicode escape>"},
|
56
|
-
|
57
|
-
%q({"a": "\u003cbr /\u003e"}) => {
|
58
|
-
%q({"b":["\u003ci\u003e","\u003cb\u003e","\u003cu\u003e"]}) => {
|
54
|
+
%({"a":1}) => { "a" => 1 },
|
55
|
+
%({"a": ""}) => { "a" => "" },
|
56
|
+
%({"a":"\\""}) => { "a" => "\"" },
|
57
|
+
%({"a": null}) => { "a" => nil },
|
58
|
+
%({"a": true}) => { "a" => true },
|
59
|
+
%({"a": false}) => { "a" => false },
|
60
|
+
'{"bad":"\\\\","trailing":""}' => { "bad" => "\\", "trailing" => "" },
|
61
|
+
%q({"a": "http:\/\/test.host\/posts\/1"}) => { "a" => "http://test.host/posts/1" },
|
62
|
+
%q({"a": "\u003cunicode\u0020escape\u003e"}) => { "a" => "<unicode escape>" },
|
63
|
+
'{"a": "\\\\u0020skip double backslashes"}' => { "a" => "\\u0020skip double backslashes" },
|
64
|
+
%q({"a": "\u003cbr /\u003e"}) => { "a" => "<br />" },
|
65
|
+
%q({"b":["\u003ci\u003e","\u003cb\u003e","\u003cu\u003e"]}) => { "b" => ["<i>", "<b>", "<u>"] },
|
59
66
|
# test combination of dates and escaped or unicode encoded data in arrays
|
60
67
|
%q([{"d":"1970-01-01", "s":"\u0020escape"},{"d":"1970-01-01", "s":"\u0020escape"}]) =>
|
61
|
-
[{
|
68
|
+
[{ "d" => Date.new(1970, 1, 1), "s" => " escape" }, { "d" => Date.new(1970, 1, 1), "s" => " escape" }],
|
62
69
|
%q([{"d":"1970-01-01","s":"http:\/\/example.com"},{"d":"1970-01-01","s":"http:\/\/example.com"}]) =>
|
63
|
-
[{
|
64
|
-
{
|
70
|
+
[{ "d" => Date.new(1970, 1, 1), "s" => "http://example.com" },
|
71
|
+
{ "d" => Date.new(1970, 1, 1), "s" => "http://example.com" }],
|
65
72
|
# tests escaping of "\n" char with Yaml backend
|
66
|
-
%q({"a":"\n"})
|
67
|
-
%q({"a":"\u000a"}) => {"a"=>"\n"},
|
68
|
-
%q({"a":"Line1\u000aLine2"}) => {"a"=>"Line1\nLine2"},
|
73
|
+
%q({"a":"\n"}) => { "a" => "\n" },
|
74
|
+
%q({"a":"\u000a"}) => { "a" => "\n" },
|
75
|
+
%q({"a":"Line1\u000aLine2"}) => { "a" => "Line1\nLine2" },
|
69
76
|
# prevent json unmarshalling
|
70
|
-
|
77
|
+
'{"json_class":"TestJSONDecoding::Foo"}' => { "json_class" => "TestJSONDecoding::Foo" },
|
71
78
|
# json "fragments" - these are invalid JSON, but ActionPack relies on this
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
+
'"a string"' => "a string",
|
80
|
+
"1.1" => 1.1,
|
81
|
+
"1" => 1,
|
82
|
+
"-1" => -1,
|
83
|
+
"true" => true,
|
84
|
+
"false" => false,
|
85
|
+
"null" => nil
|
79
86
|
}
|
80
87
|
|
81
88
|
TESTS.each_with_index do |(json, expected), index|
|
89
|
+
fail_message = "JSON decoding failed for #{json}"
|
90
|
+
|
82
91
|
test "json decodes #{index}" do
|
83
|
-
with_tz_default
|
92
|
+
with_tz_default "Eastern Time (US & Canada)" do
|
84
93
|
with_parse_json_times(true) do
|
85
94
|
silence_warnings do
|
86
95
|
if expected.nil?
|
87
|
-
assert_nil
|
96
|
+
assert_nil ActiveSupport::JSON.decode(json), fail_message
|
88
97
|
else
|
89
|
-
assert_equal
|
98
|
+
assert_equal expected, ActiveSupport::JSON.decode(json), fail_message
|
90
99
|
end
|
91
100
|
end
|
92
101
|
end
|
@@ -96,7 +105,7 @@ class TestJSONDecoding < ActiveSupport::TestCase
|
|
96
105
|
|
97
106
|
test "json decodes time json with time parsing disabled" do
|
98
107
|
with_parse_json_times(false) do
|
99
|
-
expected = {"a" => "2007-01-01 01:12:34 Z"}
|
108
|
+
expected = { "a" => "2007-01-01 01:12:34 Z" }
|
100
109
|
assert_equal expected, ActiveSupport::JSON.decode(%({"a": "2007-01-01 01:12:34 Z"}))
|
101
110
|
end
|
102
111
|
end
|
@@ -114,12 +123,11 @@ class TestJSONDecoding < ActiveSupport::TestCase
|
|
114
123
|
|
115
124
|
private
|
116
125
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
126
|
+
def with_parse_json_times(value)
|
127
|
+
old_value = ActiveSupport.parse_json_times
|
128
|
+
ActiveSupport.parse_json_times = value
|
129
|
+
yield
|
130
|
+
ensure
|
131
|
+
ActiveSupport.parse_json_times = old_value
|
132
|
+
end
|
124
133
|
end
|
125
|
-
|
@@ -1,11 +1,13 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
require
|
4
|
-
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "securerandom"
|
4
|
+
require_relative "abstract_unit"
|
5
|
+
require "active_support/core_ext/string/inflections"
|
6
|
+
require "active_support/core_ext/regexp"
|
7
|
+
require "active_support/json"
|
8
|
+
require "active_support/time"
|
9
|
+
require_relative "time_zone_test_helpers"
|
10
|
+
require_relative "encoding_test_cases"
|
9
11
|
|
10
12
|
require 'oj'
|
11
13
|
|
@@ -18,9 +20,17 @@ Oj::Rails.optimize()
|
|
18
20
|
class TestJSONEncoding < ActiveSupport::TestCase
|
19
21
|
include TimeZoneTestHelpers
|
20
22
|
|
23
|
+
# Added for testing if Oj is used.
|
24
|
+
test "oj is used as an encoder" do
|
25
|
+
assert_equal ActiveSupport.json_encoder, Oj::Rails::Encoder
|
26
|
+
end
|
27
|
+
|
21
28
|
def sorted_json(json)
|
22
|
-
|
23
|
-
|
29
|
+
if json.start_with?("{") && json.end_with?("}")
|
30
|
+
"{" + json[1..-2].split(",").sort.join(",") + "}"
|
31
|
+
else
|
32
|
+
json
|
33
|
+
end
|
24
34
|
end
|
25
35
|
|
26
36
|
JSONTest::EncodingTestCases.constants.each do |class_tests|
|
@@ -28,8 +38,10 @@ class TestJSONEncoding < ActiveSupport::TestCase
|
|
28
38
|
begin
|
29
39
|
prev = ActiveSupport.use_standard_json_time_format
|
30
40
|
|
31
|
-
|
32
|
-
|
41
|
+
standard_class_tests = /Standard/.match?(class_tests)
|
42
|
+
|
43
|
+
ActiveSupport.escape_html_entities_in_json = !standard_class_tests
|
44
|
+
ActiveSupport.use_standard_json_time_format = standard_class_tests
|
33
45
|
JSONTest::EncodingTestCases.const_get(class_tests).each do |pair|
|
34
46
|
assert_equal pair.last, sorted_json(ActiveSupport::JSON.encode(pair.first))
|
35
47
|
end
|
@@ -50,12 +62,12 @@ class TestJSONEncoding < ActiveSupport::TestCase
|
|
50
62
|
end
|
51
63
|
|
52
64
|
def test_hash_encoding
|
53
|
-
assert_equal %({\"a\":\"b\"}), ActiveSupport::JSON.encode(:
|
54
|
-
assert_equal %({\"a\":1}), ActiveSupport::JSON.encode(
|
55
|
-
assert_equal %({\"a\":[1,2]}), ActiveSupport::JSON.encode(
|
65
|
+
assert_equal %({\"a\":\"b\"}), ActiveSupport::JSON.encode(a: :b)
|
66
|
+
assert_equal %({\"a\":1}), ActiveSupport::JSON.encode("a" => 1)
|
67
|
+
assert_equal %({\"a\":[1,2]}), ActiveSupport::JSON.encode("a" => [1, 2])
|
56
68
|
assert_equal %({"1":2}), ActiveSupport::JSON.encode(1 => 2)
|
57
69
|
|
58
|
-
assert_equal %({\"a\":\"b\",\"c\":\"d\"}), sorted_json(ActiveSupport::JSON.encode(:
|
70
|
+
assert_equal %({\"a\":\"b\",\"c\":\"d\"}), sorted_json(ActiveSupport::JSON.encode(a: :b, c: :d))
|
59
71
|
end
|
60
72
|
|
61
73
|
def test_hash_keys_encoding
|
@@ -68,28 +80,28 @@ class TestJSONEncoding < ActiveSupport::TestCase
|
|
68
80
|
def test_utf8_string_encoded_properly
|
69
81
|
# The original test seems to expect that
|
70
82
|
# ActiveSupport.escape_html_entities_in_json reverts to true even after
|
71
|
-
# being set to false. I haven't been able to figure that out so the value
|
72
|
-
#
|
73
|
-
#
|
74
|
-
ActiveSupport.escape_html_entities_in_json
|
75
|
-
result = ActiveSupport::JSON.encode(
|
83
|
+
# being set to false. I haven't been able to figure that out so the value is
|
84
|
+
# set to true, the default, before running the test. This might be wrong but
|
85
|
+
# for now it will have to do.
|
86
|
+
ActiveSupport.escape_html_entities_in_json = true
|
87
|
+
result = ActiveSupport::JSON.encode("€2.99")
|
76
88
|
assert_equal '"€2.99"', result
|
77
89
|
assert_equal(Encoding::UTF_8, result.encoding)
|
78
90
|
|
79
|
-
result = ActiveSupport::JSON.encode(
|
91
|
+
result = ActiveSupport::JSON.encode("✎☺")
|
80
92
|
assert_equal '"✎☺"', result
|
81
93
|
assert_equal(Encoding::UTF_8, result.encoding)
|
82
94
|
end
|
83
95
|
|
84
96
|
def test_non_utf8_string_transcodes
|
85
|
-
s =
|
97
|
+
s = "二".encode("Shift_JIS")
|
86
98
|
result = ActiveSupport::JSON.encode(s)
|
87
99
|
assert_equal '"二"', result
|
88
100
|
assert_equal Encoding::UTF_8, result.encoding
|
89
101
|
end
|
90
102
|
|
91
103
|
def test_wide_utf8_chars
|
92
|
-
w =
|
104
|
+
w = "𠜎"
|
93
105
|
result = ActiveSupport::JSON.encode(w)
|
94
106
|
assert_equal '"𠜎"', result
|
95
107
|
end
|
@@ -98,33 +110,33 @@ class TestJSONEncoding < ActiveSupport::TestCase
|
|
98
110
|
hash = { string: "𐒑" }
|
99
111
|
json = ActiveSupport::JSON.encode(hash)
|
100
112
|
decoded_hash = ActiveSupport::JSON.decode(json)
|
101
|
-
assert_equal "𐒑", decoded_hash[
|
113
|
+
assert_equal "𐒑", decoded_hash["string"]
|
102
114
|
end
|
103
115
|
|
104
116
|
def test_hash_key_identifiers_are_always_quoted
|
105
|
-
values = {0 => 0, 1 => 1, :_ => :_, "$" => "$", "a" => "a", :A => :A, :A0 => :A0, "A0B" => "A0B"}
|
117
|
+
values = { 0 => 0, 1 => 1, :_ => :_, "$" => "$", "a" => "a", :A => :A, :A0 => :A0, "A0B" => "A0B" }
|
106
118
|
assert_equal %w( "$" "A" "A0" "A0B" "_" "a" "0" "1" ).sort, object_keys(ActiveSupport::JSON.encode(values))
|
107
119
|
end
|
108
120
|
|
109
121
|
def test_hash_should_allow_key_filtering_with_only
|
110
|
-
assert_equal %({"a":1}), ActiveSupport::JSON.encode({
|
122
|
+
assert_equal %({"a":1}), ActiveSupport::JSON.encode({ "a" => 1, :b => 2, :c => 3 }, { only: "a" })
|
111
123
|
end
|
112
124
|
|
113
125
|
def test_hash_should_allow_key_filtering_with_except
|
114
|
-
assert_equal %({"b":2}), ActiveSupport::JSON.encode({
|
126
|
+
assert_equal %({"b":2}), ActiveSupport::JSON.encode({ "foo" => "bar", :b => 2, :c => 3 }, { except: ["foo", :c] })
|
115
127
|
end
|
116
128
|
|
117
129
|
def test_time_to_json_includes_local_offset
|
118
130
|
with_standard_json_time_format(true) do
|
119
|
-
with_env_tz
|
120
|
-
assert_equal %("2005-02-01T15:15:10.000-05:00"), ActiveSupport::JSON.encode(Time.local(2005,2,1,15,15,10))
|
131
|
+
with_env_tz "US/Eastern" do
|
132
|
+
assert_equal %("2005-02-01T15:15:10.000-05:00"), ActiveSupport::JSON.encode(Time.local(2005, 2, 1, 15, 15, 10))
|
121
133
|
end
|
122
134
|
end
|
123
135
|
end
|
124
136
|
|
125
137
|
def test_hash_with_time_to_json
|
126
138
|
with_standard_json_time_format(false) do
|
127
|
-
assert_equal '{"time":"2009/01/01 00:00:00 +0000"}', { :
|
139
|
+
assert_equal '{"time":"2009/01/01 00:00:00 +0000"}', { time: Time.utc(2009) }.to_json
|
128
140
|
end
|
129
141
|
end
|
130
142
|
|
@@ -132,8 +144,8 @@ class TestJSONEncoding < ActiveSupport::TestCase
|
|
132
144
|
assert_nothing_raised do
|
133
145
|
hash = {
|
134
146
|
"CHI" => {
|
135
|
-
:
|
136
|
-
:
|
147
|
+
display_name: "chicago",
|
148
|
+
latitude: 123.234
|
137
149
|
}
|
138
150
|
}
|
139
151
|
ActiveSupport::JSON.encode(hash)
|
@@ -142,64 +154,64 @@ class TestJSONEncoding < ActiveSupport::TestCase
|
|
142
154
|
|
143
155
|
def test_hash_like_with_options
|
144
156
|
h = JSONTest::Hashlike.new
|
145
|
-
json = h.to_json :
|
157
|
+
json = h.to_json only: [:foo]
|
146
158
|
|
147
|
-
assert_equal({"foo"=>"hello"}, JSON.parse(json))
|
159
|
+
assert_equal({ "foo" => "hello" }, JSON.parse(json))
|
148
160
|
end
|
149
161
|
|
150
162
|
def test_object_to_json_with_options
|
151
163
|
obj = Object.new
|
152
164
|
obj.instance_variable_set :@foo, "hello"
|
153
165
|
obj.instance_variable_set :@bar, "world"
|
154
|
-
json = obj.to_json :
|
166
|
+
json = obj.to_json only: ["foo"]
|
155
167
|
|
156
|
-
assert_equal({"foo"=>"hello"}, JSON.parse(json))
|
168
|
+
assert_equal({ "foo" => "hello" }, JSON.parse(json))
|
157
169
|
end
|
158
170
|
|
159
171
|
def test_struct_to_json_with_options
|
160
172
|
struct = Struct.new(:foo, :bar).new
|
161
173
|
struct.foo = "hello"
|
162
174
|
struct.bar = "world"
|
163
|
-
json = struct.to_json :
|
175
|
+
json = struct.to_json only: [:foo]
|
164
176
|
|
165
|
-
assert_equal({"foo"=>"hello"}, JSON.parse(json))
|
177
|
+
assert_equal({ "foo" => "hello" }, JSON.parse(json))
|
166
178
|
end
|
167
179
|
|
168
180
|
def test_hash_should_pass_encoding_options_to_children_in_as_json
|
169
181
|
person = {
|
170
|
-
:
|
171
|
-
:
|
172
|
-
:
|
173
|
-
:
|
182
|
+
name: "John",
|
183
|
+
address: {
|
184
|
+
city: "London",
|
185
|
+
country: "UK"
|
174
186
|
}
|
175
187
|
}
|
176
|
-
json = person.as_json :
|
188
|
+
json = person.as_json only: [:address, :city]
|
177
189
|
|
178
|
-
assert_equal({
|
190
|
+
assert_equal({ "address" => { "city" => "London" } }, json)
|
179
191
|
end
|
180
192
|
|
181
193
|
def test_hash_should_pass_encoding_options_to_children_in_to_json
|
182
194
|
person = {
|
183
|
-
:
|
184
|
-
:
|
185
|
-
:
|
186
|
-
:
|
195
|
+
name: "John",
|
196
|
+
address: {
|
197
|
+
city: "London",
|
198
|
+
country: "UK"
|
187
199
|
}
|
188
200
|
}
|
189
|
-
json = person.to_json :
|
201
|
+
json = person.to_json only: [:address, :city]
|
190
202
|
|
191
203
|
assert_equal(%({"address":{"city":"London"}}), json)
|
192
204
|
end
|
193
205
|
|
194
206
|
def test_array_should_pass_encoding_options_to_children_in_as_json
|
195
207
|
people = [
|
196
|
-
{ :
|
197
|
-
{ :
|
208
|
+
{ name: "John", address: { city: "London", country: "UK" } },
|
209
|
+
{ name: "Jean", address: { city: "Paris", country: "France" } }
|
198
210
|
]
|
199
|
-
json = people.as_json :
|
211
|
+
json = people.as_json only: [:address, :city]
|
200
212
|
expected = [
|
201
|
-
{
|
202
|
-
{
|
213
|
+
{ "address" => { "city" => "London" } },
|
214
|
+
{ "address" => { "city" => "Paris" } }
|
203
215
|
]
|
204
216
|
|
205
217
|
assert_equal(expected, json)
|
@@ -207,20 +219,20 @@ class TestJSONEncoding < ActiveSupport::TestCase
|
|
207
219
|
|
208
220
|
def test_array_should_pass_encoding_options_to_children_in_to_json
|
209
221
|
people = [
|
210
|
-
{ :
|
211
|
-
{ :
|
222
|
+
{ name: "John", address: { city: "London", country: "UK" } },
|
223
|
+
{ name: "Jean", address: { city: "Paris", country: "France" } }
|
212
224
|
]
|
213
|
-
json = people.to_json :
|
225
|
+
json = people.to_json only: [:address, :city]
|
214
226
|
|
215
227
|
assert_equal(%([{"address":{"city":"London"}},{"address":{"city":"Paris"}}]), json)
|
216
228
|
end
|
217
229
|
|
218
230
|
People = Class.new(BasicObject) do
|
219
231
|
include Enumerable
|
220
|
-
def initialize
|
232
|
+
def initialize
|
221
233
|
@people = [
|
222
|
-
{ :
|
223
|
-
{ :
|
234
|
+
{ name: "John", address: { city: "London", country: "UK" } },
|
235
|
+
{ name: "Jean", address: { city: "Paris", country: "France" } }
|
224
236
|
]
|
225
237
|
end
|
226
238
|
def each(*, &blk)
|
@@ -232,32 +244,32 @@ class TestJSONEncoding < ActiveSupport::TestCase
|
|
232
244
|
end
|
233
245
|
|
234
246
|
def test_enumerable_should_generate_json_with_as_json
|
235
|
-
json = People.new.as_json :
|
247
|
+
json = People.new.as_json only: [:address, :city]
|
236
248
|
expected = [
|
237
|
-
{
|
238
|
-
{
|
249
|
+
{ "address" => { "city" => "London" } },
|
250
|
+
{ "address" => { "city" => "Paris" } }
|
239
251
|
]
|
240
252
|
|
241
253
|
assert_equal(expected, json)
|
242
254
|
end
|
243
255
|
|
244
256
|
def test_enumerable_should_generate_json_with_to_json
|
245
|
-
json = People.new.to_json :
|
257
|
+
json = People.new.to_json only: [:address, :city]
|
246
258
|
assert_equal(%([{"address":{"city":"London"}},{"address":{"city":"Paris"}}]), json)
|
247
259
|
end
|
248
260
|
|
249
261
|
def test_enumerable_should_pass_encoding_options_to_children_in_as_json
|
250
|
-
json = People.new.each.as_json :
|
262
|
+
json = People.new.each.as_json only: [:address, :city]
|
251
263
|
expected = [
|
252
|
-
{
|
253
|
-
{
|
264
|
+
{ "address" => { "city" => "London" } },
|
265
|
+
{ "address" => { "city" => "Paris" } }
|
254
266
|
]
|
255
267
|
|
256
268
|
assert_equal(expected, json)
|
257
269
|
end
|
258
270
|
|
259
271
|
def test_enumerable_should_pass_encoding_options_to_children_in_to_json
|
260
|
-
json = People.new.each.to_json :
|
272
|
+
json = People.new.each.to_json only: [:address, :city]
|
261
273
|
|
262
274
|
assert_equal(%([{"address":{"city":"London"}},{"address":{"city":"Paris"}}]), json)
|
263
275
|
end
|
@@ -265,7 +277,7 @@ class TestJSONEncoding < ActiveSupport::TestCase
|
|
265
277
|
class CustomWithOptions
|
266
278
|
attr_accessor :foo, :bar
|
267
279
|
|
268
|
-
def as_json(options={})
|
280
|
+
def as_json(options = {})
|
269
281
|
options[:only] = %w(foo bar)
|
270
282
|
super(options)
|
271
283
|
end
|
@@ -276,9 +288,9 @@ class TestJSONEncoding < ActiveSupport::TestCase
|
|
276
288
|
f.foo = "hello"
|
277
289
|
f.bar = "world"
|
278
290
|
|
279
|
-
hash = {"foo" => f, "other_hash" => {"foo" => "other_foo", "test" => "other_test"}}
|
280
|
-
assert_equal({"foo"=>{"foo"=>"hello","bar"=>"world"},
|
281
|
-
"other_hash" => {"foo"=>"other_foo","test"=>"other_test"}}, ActiveSupport::JSON.decode(hash.to_json))
|
291
|
+
hash = { "foo" => f, "other_hash" => { "foo" => "other_foo", "test" => "other_test" } }
|
292
|
+
assert_equal({ "foo" => { "foo" => "hello", "bar" => "world" },
|
293
|
+
"other_hash" => { "foo" => "other_foo", "test" => "other_test" } }, ActiveSupport::JSON.decode(hash.to_json))
|
282
294
|
end
|
283
295
|
|
284
296
|
def test_array_to_json_should_not_keep_options_around
|
@@ -286,9 +298,9 @@ class TestJSONEncoding < ActiveSupport::TestCase
|
|
286
298
|
f.foo = "hello"
|
287
299
|
f.bar = "world"
|
288
300
|
|
289
|
-
array = [f, {"foo" => "other_foo", "test" => "other_test"}]
|
290
|
-
assert_equal([{"foo"=>"hello","bar"=>"world"},
|
291
|
-
{"foo"=>"other_foo","test"=>"other_test"}], ActiveSupport::JSON.decode(array.to_json))
|
301
|
+
array = [f, { "foo" => "other_foo", "test" => "other_test" }]
|
302
|
+
assert_equal([{ "foo" => "hello", "bar" => "world" },
|
303
|
+
{ "foo" => "other_foo", "test" => "other_test" }], ActiveSupport::JSON.decode(array.to_json))
|
292
304
|
end
|
293
305
|
|
294
306
|
class OptionsTest
|
@@ -299,7 +311,7 @@ class TestJSONEncoding < ActiveSupport::TestCase
|
|
299
311
|
|
300
312
|
def test_hash_as_json_without_options
|
301
313
|
json = { foo: OptionsTest.new }.as_json
|
302
|
-
assert_equal({"foo" => :default}, json)
|
314
|
+
assert_equal({ "foo" => :default }, json)
|
303
315
|
end
|
304
316
|
|
305
317
|
def test_array_as_json_without_options
|
@@ -308,13 +320,12 @@ class TestJSONEncoding < ActiveSupport::TestCase
|
|
308
320
|
end
|
309
321
|
|
310
322
|
def test_struct_encoding
|
311
|
-
Struct.new(
|
312
|
-
Struct.new(
|
313
|
-
Struct.new(
|
314
|
-
user_email = Struct::UserNameAndEmail.new
|
315
|
-
user_birthday = Struct::UserNameAndDate.new
|
316
|
-
custom = Struct::Custom.new
|
317
|
-
|
323
|
+
Struct.new("UserNameAndEmail", :name, :email)
|
324
|
+
Struct.new("UserNameAndDate", :name, :date)
|
325
|
+
Struct.new("Custom", :name, :sub)
|
326
|
+
user_email = Struct::UserNameAndEmail.new "David", "sample@example.com"
|
327
|
+
user_birthday = Struct::UserNameAndDate.new "David", Date.new(2010, 01, 01)
|
328
|
+
custom = Struct::Custom.new "David", user_birthday
|
318
329
|
|
319
330
|
json_strings = ""
|
320
331
|
json_string_and_date = ""
|
@@ -326,20 +337,20 @@ class TestJSONEncoding < ActiveSupport::TestCase
|
|
326
337
|
json_custom = custom.to_json
|
327
338
|
end
|
328
339
|
|
329
|
-
assert_equal({"name" => "David",
|
340
|
+
assert_equal({ "name" => "David",
|
330
341
|
"sub" => {
|
331
342
|
"name" => "David",
|
332
|
-
"date" => "2010-01-01" }}, ActiveSupport::JSON.decode(json_custom))
|
343
|
+
"date" => "2010-01-01" } }, ActiveSupport::JSON.decode(json_custom))
|
333
344
|
|
334
|
-
assert_equal({"name" => "David", "email" => "sample@example.com"},
|
345
|
+
assert_equal({ "name" => "David", "email" => "sample@example.com" },
|
335
346
|
ActiveSupport::JSON.decode(json_strings))
|
336
347
|
|
337
|
-
assert_equal({"name" => "David", "date" => "2010-01-01"},
|
348
|
+
assert_equal({ "name" => "David", "date" => "2010-01-01" },
|
338
349
|
ActiveSupport::JSON.decode(json_string_and_date))
|
339
350
|
end
|
340
351
|
|
341
352
|
def test_nil_true_and_false_represented_as_themselves
|
342
|
-
assert_nil
|
353
|
+
assert_nil nil.as_json
|
343
354
|
assert_equal true, true.as_json
|
344
355
|
assert_equal false, false.as_json
|
345
356
|
end
|
@@ -351,7 +362,7 @@ class TestJSONEncoding < ActiveSupport::TestCase
|
|
351
362
|
super
|
352
363
|
end
|
353
364
|
|
354
|
-
def as_json(options={})
|
365
|
+
def as_json(options = {})
|
355
366
|
@as_json_called = true
|
356
367
|
super
|
357
368
|
end
|
@@ -391,7 +402,7 @@ EXPECTED
|
|
391
402
|
|
392
403
|
def test_twz_to_json_with_use_standard_json_time_format_config_set_to_false
|
393
404
|
with_standard_json_time_format(false) do
|
394
|
-
zone = ActiveSupport::TimeZone[
|
405
|
+
zone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"]
|
395
406
|
time = ActiveSupport::TimeWithZone.new(Time.utc(2000), zone)
|
396
407
|
assert_equal "\"1999/12/31 19:00:00 -0500\"", ActiveSupport::JSON.encode(time)
|
397
408
|
end
|
@@ -399,7 +410,7 @@ EXPECTED
|
|
399
410
|
|
400
411
|
def test_twz_to_json_with_use_standard_json_time_format_config_set_to_true
|
401
412
|
with_standard_json_time_format(true) do
|
402
|
-
zone = ActiveSupport::TimeZone[
|
413
|
+
zone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"]
|
403
414
|
time = ActiveSupport::TimeWithZone.new(Time.utc(2000), zone)
|
404
415
|
assert_equal "\"1999-12-31T19:00:00.000-05:00\"", ActiveSupport::JSON.encode(time)
|
405
416
|
end
|
@@ -408,7 +419,7 @@ EXPECTED
|
|
408
419
|
def test_twz_to_json_with_custom_time_precision
|
409
420
|
with_standard_json_time_format(true) do
|
410
421
|
with_time_precision(0) do
|
411
|
-
zone = ActiveSupport::TimeZone[
|
422
|
+
zone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"]
|
412
423
|
time = ActiveSupport::TimeWithZone.new(Time.utc(2000), zone)
|
413
424
|
assert_equal "\"1999-12-31T19:00:00-05:00\"", ActiveSupport::JSON.encode(time)
|
414
425
|
end
|
@@ -432,7 +443,7 @@ EXPECTED
|
|
432
443
|
end
|
433
444
|
|
434
445
|
def test_twz_to_json_when_wrapping_a_date_time
|
435
|
-
zone = ActiveSupport::TimeZone[
|
446
|
+
zone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"]
|
436
447
|
time = ActiveSupport::TimeWithZone.new(DateTime.new(2000), zone)
|
437
448
|
assert_equal '"1999-12-31T19:00:00.000-05:00"', ActiveSupport::JSON.encode(time)
|
438
449
|
end
|
@@ -454,7 +465,7 @@ EXPECTED
|
|
454
465
|
|
455
466
|
class NaNNumber
|
456
467
|
def as_json(options = nil)
|
457
|
-
{ "number" => Float::
|
468
|
+
{ "number" => Float::NAN }
|
458
469
|
end
|
459
470
|
end
|
460
471
|
|
@@ -462,7 +473,11 @@ EXPECTED
|
|
462
473
|
assert_equal '{"number":null}', NaNNumber.new.to_json
|
463
474
|
end
|
464
475
|
|
465
|
-
|
476
|
+
def test_to_json_works_on_io_objects
|
477
|
+
assert_equal STDOUT.to_s.to_json, STDOUT.to_json
|
478
|
+
end
|
479
|
+
|
480
|
+
private
|
466
481
|
|
467
482
|
def object_keys(json_object)
|
468
483
|
json_object[1..-2].scan(/([^{}:,\s]+):/).flatten.sort
|