oj 3.9.2 → 3.10.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -899,7 +899,7 @@ CLEANUP:
899
899
  VALUE args[] = { oj_encode(rb_str_new2(pi->err.msg)) };
900
900
 
901
901
  if (pi->err.clas == oj_parse_error_class) {
902
- // The error was an Oj::ParseError so change to a JSON::ParseError.
902
+ // The error was an Oj::ParseError so change to a JSON::ParserError.
903
903
  pi->err.clas = oj_json_parser_error_class;
904
904
  }
905
905
  rb_exc_raise(rb_class_new_instance(1, args, pi->err.clas));
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Oj
3
3
  # Current version of the module.
4
- VERSION = '3.9.2'
4
+ VERSION = '3.10.0'
5
5
  end
@@ -26,44 +26,44 @@ directly. If Rails mode is also desired then use the `Oj.default_options` to
26
26
  change the default mode.
27
27
 
28
28
  Some of the Oj options are supported as arguments to the encoder if called
29
- from Oj::Rails.encode() but when using the Oj::Rails::Encoder class the
30
- encode() method does not support optional arguments as required by the
29
+ from `Oj::Rails.encode()` but when using the `Oj::Rails::Encoder` class the
30
+ `encode()` method does not support optional arguments as required by the
31
31
  ActiveSupport compliance guidelines. The general approach Rails takes for
32
32
  configuring encoding options is to either set global values or to create a new
33
33
  instance of the Encoder class and provide options in the initializer.
34
34
 
35
35
  The globals that ActiveSupport uses for encoding are:
36
36
 
37
- * ActiveSupport::JSON::Encoding.use_standard_json_time_format
38
- * ActiveSupport::JSON::Encoding.escape_html_entities_in_json
39
- * ActiveSupport::JSON::Encoding.time_precision
40
- * ActiveSupport::JSON::Encoding.json_encoder
37
+ * `ActiveSupport::JSON::Encoding.use_standard_json_time_format`
38
+ * `ActiveSupport::JSON::Encoding.escape_html_entities_in_json`
39
+ * `ActiveSupport::JSON::Encoding.time_precision`
40
+ * `ActiveSupport::JSON::Encoding.json_encoder`
41
41
 
42
42
  Those globals are aliased to also be accessed from the ActiveSupport module
43
- directly so ActiveSupport::JSON::Encoding.time_precision can also be accessed
44
- from ActiveSupport.time_precision. Oj makes use of these globals in mimicing
45
- Rails after the Oj::Rails.set_encode() method is called. That also sets the
46
- ActiveSupport.json_encoder to the Oj::Rails::Encoder class.
43
+ directly so `ActiveSupport::JSON::Encoding.time_precision` can also be accessed
44
+ from `ActiveSupport.time_precision`. Oj makes use of these globals in mimicing
45
+ Rails after the `Oj::Rails.set_encode()` method is called. That also sets the
46
+ `ActiveSupport.json_encoder` to the `Oj::Rails::Encoder` class.
47
47
 
48
- Options passed into a call to to_json() are passed to the as_json()
48
+ Options passed into a call to `to_json()` are passed to the `as_json()`
49
49
  methods. These are mostly ignored by Oj and simply passed on without
50
50
  modifications as per the guidelines. The exception to this are the options
51
- specific to Oj such as the :circular option which it used to detect circular
51
+ specific to Oj such as the `:circular` option which it used to detect circular
52
52
  references while encoding.
53
53
 
54
54
  By default Oj acts like the ActiveSupport encoder and honors any changes in
55
- the as_json() methods. There are some optimized Oj encoders for some
56
- classes. When the optimized encoder it toggled the as_json() methods will not
55
+ the `as_json()` methods. There are some optimized Oj encoders for some
56
+ classes. When the optimized encoder it toggled the `as_json()` methods will not
57
57
  be called for that class but instead the optimized version will be called. The
58
58
  optimized version is the same as the ActiveSupport default encoding for a
59
- given class. The optimized versions are toggled with the optimize() and
60
- deoptimize() methods. There is a default optimized version for every class
59
+ given class. The optimized versions are toggled with the `optimize()` and
60
+ `deoptimize()` methods. There is a default optimized version for every class
61
61
  that takes the visible attributes and encodes them but that may not be the
62
62
  same as what Rails uses. Trial and error is the best approach for classes not
63
63
  listed here.
64
64
 
65
65
  The classes that can be put in optimized mode and are optimized when
66
- Oj::Rails.optimize is called with no arguments are:
66
+ `Oj::Rails.optimize` is called with no arguments are:
67
67
 
68
68
  * Array
69
69
  * BigDecimal
@@ -77,8 +77,8 @@ Oj::Rails.optimize is called with no arguments are:
77
77
  * any class inheriting from ActiveRecord::Base
78
78
  * any other class where all attributes should be dumped
79
79
 
80
- The ActiveSupport decoder is the JSON.parse() method. Calling the
81
- Oj::Rails.set_decoder() method replaces that method with the Oj equivalent.
80
+ The ActiveSupport decoder is the `JSON.parse()` method. Calling the
81
+ `Oj::Rails.set_decoder()` method replaces that method with the Oj equivalent.
82
82
 
83
83
  ### Notes:
84
84
 
@@ -87,8 +87,8 @@ Oj::Rails.set_decoder() method replaces that method with the Oj equivalent.
87
87
  significant digits which can be either 16 or 17 depending on the value.
88
88
 
89
89
  2. Optimized Hashs do not collapse keys that become the same in the output. As
90
- an example, a non-String object that has a to_s() method will become the
91
- return value of the to_s() method in the output without checking to see if
90
+ an example, a non-String object that has a `to_s()` method will become the
91
+ return value of the `to_s()` method in the output without checking to see if
92
92
  that has already been used. This could occur is a mix of String and Symbols
93
93
  are used as keys or if a other non-String objects such as Numerics are mixed
94
94
  with numbers as Strings.
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ ORIG_ARGV = ARGV.dup
4
+
5
+ require "active_support/core_ext/kernel/reporting"
6
+
7
+ silence_warnings do
8
+ Encoding.default_internal = Encoding::UTF_8
9
+ Encoding.default_external = Encoding::UTF_8
10
+ end
11
+
12
+ require "active_support/testing/autorun"
13
+ require "active_support/testing/method_call_assertions"
14
+
15
+ ENV["NO_RELOAD"] = "1"
16
+ require "active_support"
17
+
18
+ Thread.abort_on_exception = true
19
+
20
+ # Show backtraces for deprecated behavior for quicker cleanup.
21
+ ActiveSupport::Deprecation.debug = true
22
+
23
+ # Default to old to_time behavior but allow running tests with new behavior
24
+ ActiveSupport.to_time_preserves_timezone = ENV["PRESERVE_TIMEZONES"] == "1"
25
+
26
+ # Disable available locale checks to avoid warnings running the test suite.
27
+ I18n.enforce_available_locales = false
28
+
29
+ class ActiveSupport::TestCase
30
+ include ActiveSupport::Testing::MethodCallAssertions
31
+
32
+ # Skips the current run on Rubinius using Minitest::Assertions#skip
33
+ private def rubinius_skip(message = "")
34
+ skip message if RUBY_ENGINE == "rbx"
35
+ end
36
+
37
+ # Skips the current run on JRuby using Minitest::Assertions#skip
38
+ private def jruby_skip(message = "")
39
+ skip message if defined?(JRUBY_VERSION)
40
+ end
41
+
42
+ def frozen_error_class
43
+ Object.const_defined?(:FrozenError) ? FrozenError : RuntimeError
44
+ end
45
+ end
@@ -1,7 +1,9 @@
1
- require 'activesupport5/test_helper'
2
- require 'active_support/json'
3
- require 'active_support/time'
4
- require 'activesupport5/time_zone_test_helpers'
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}}) => {"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"}) => {'a' => Date.new(2007, 1, 1)},
30
- %({"a": "2007-01-01 01:12:34 Z"}) => {'a' => Time.utc(2007, 1, 1, 1, 12, 34)},
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"}) => {'a' => Time.new(2007, 1, 1, 1, 12, 34, "-05:00")},
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"}) => {'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"}) => {'a' => Time.new(2009, 8, 10, 19, 1, 2, "-04:00")},
39
- %({"a": "2009-08-10T19:01:02Z"}) => {'a' => Time.utc(2009, 8, 10, 19, 1, 2)},
40
- %({"a": "2009-08-10T19:01:02+02:00"}) => {'a' => Time.utc(2009, 8, 10, 17, 1, 2)},
41
- %({"a": "2009-08-10T19:01:02-05:00"}) => {'a' => Time.utc(2009, 8, 11, 00, 1, 2)},
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 "}) => {'a' => " 2007-01-01 01:12:34 Z "},
44
- %({"a": "2007-01-01 : it's your birthday"}) => {'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}) => {"a" => 1},
48
- %({"a": ""}) => {"a" => ""},
49
- %({"a":"\\""}) => {"a" => "\""},
50
- %({"a": null}) => {"a" => nil},
51
- %({"a": true}) => {"a" => true},
52
- %({"a": false}) => {"a" => false},
53
- %q({"bad":"\\\\","trailing":""}) => {"bad" => "\\", "trailing" => ""},
54
- %q({"a": "http:\/\/test.host\/posts\/1"}) => {"a" => "http://test.host/posts/1"},
55
- %q({"a": "\u003cunicode\u0020escape\u003e"}) => {"a" => "<unicode escape>"},
56
- %q({"a": "\\\\u0020skip double backslashes"}) => {"a" => "\\u0020skip double backslashes"},
57
- %q({"a": "\u003cbr /\u003e"}) => {'a' => "<br />"},
58
- %q({"b":["\u003ci\u003e","\u003cb\u003e","\u003cu\u003e"]}) => {'b' => ["<i>","<b>","<u>"]},
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
- [{'d' => Date.new(1970, 1, 1), 's' => ' escape'},{'d' => Date.new(1970, 1, 1), 's' => ' escape'}],
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
- [{'d' => Date.new(1970, 1, 1), 's' => 'http://example.com'},
64
- {'d' => Date.new(1970, 1, 1), 's' => 'http://example.com'}],
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"}) => {"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
- %q({"json_class":"TestJSONDecoding::Foo"}) => {"json_class"=>"TestJSONDecoding::Foo"},
77
+ '{"json_class":"TestJSONDecoding::Foo"}' => { "json_class" => "TestJSONDecoding::Foo" },
71
78
  # json "fragments" - these are invalid JSON, but ActionPack relies on this
72
- %q("a string") => "a string",
73
- %q(1.1) => 1.1,
74
- %q(1) => 1,
75
- %q(-1) => -1,
76
- %q(true) => true,
77
- %q(false) => false,
78
- %q(null) => nil
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 'Eastern Time (US & Canada)' do
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(ActiveSupport::JSON.decode(json), "JSON failed for #{json}")
96
+ assert_nil ActiveSupport::JSON.decode(json), fail_message
88
97
  else
89
- assert_equal(expected, ActiveSupport::JSON.decode(json), "JSON failed for #{json}")
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
- def with_parse_json_times(value)
118
- old_value = ActiveSupport.parse_json_times
119
- ActiveSupport.parse_json_times = value
120
- yield
121
- ensure
122
- ActiveSupport.parse_json_times = old_value
123
- end
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
- # coding: utf-8
2
- require 'activesupport5/test_helper'
3
- require 'securerandom'
4
- require 'active_support/core_ext/string/inflections'
5
- require 'active_support/json'
6
- require 'active_support/time'
7
- require 'activesupport5/time_zone_test_helpers'
8
- require 'activesupport5/encoding_test_cases'
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
- return json unless json =~ /^\{.*\}$/
23
- '{' + json[1..-2].split(',').sort.join(',') + '}'
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
- ActiveSupport.escape_html_entities_in_json = class_tests !~ /^Standard/
32
- ActiveSupport.use_standard_json_time_format = class_tests =~ /^Standard/
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(:a => :b)
54
- assert_equal %({\"a\":1}), ActiveSupport::JSON.encode('a' => 1)
55
- assert_equal %({\"a\":[1,2]}), ActiveSupport::JSON.encode('a' => [1,2])
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(:a => :b, :c => :d))
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
- # is set to true, the default, before running the test. This might be
73
- # wrong but for now it will have to do.
74
- ActiveSupport.escape_html_entities_in_json = true
75
- result = ActiveSupport::JSON.encode('€2.99')
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 = ''.encode('Shift_JIS')
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['string']
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({'a' => 1, :b => 2, :c => 3}, :only => 'a')
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({'foo' => 'bar', :b => 2, :c => 3}, :except => ['foo', :c])
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 'US/Eastern' do
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"}', { :time => Time.utc(2009) }.to_json
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
- :display_name => "chicago",
136
- :latitude => 123.234
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 :only => [:foo]
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 :only => ["foo"]
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 :only => [:foo]
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
- :name => 'John',
171
- :address => {
172
- :city => 'London',
173
- :country => 'UK'
182
+ name: "John",
183
+ address: {
184
+ city: "London",
185
+ country: "UK"
174
186
  }
175
187
  }
176
- json = person.as_json :only => [:address, :city]
188
+ json = person.as_json only: [:address, :city]
177
189
 
178
- assert_equal({ 'address' => { 'city' => 'London' }}, json)
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
- :name => 'John',
184
- :address => {
185
- :city => 'London',
186
- :country => 'UK'
195
+ name: "John",
196
+ address: {
197
+ city: "London",
198
+ country: "UK"
187
199
  }
188
200
  }
189
- json = person.to_json :only => [:address, :city]
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
- { :name => 'John', :address => { :city => 'London', :country => 'UK' }},
197
- { :name => 'Jean', :address => { :city => 'Paris' , :country => 'France' }}
208
+ { name: "John", address: { city: "London", country: "UK" } },
209
+ { name: "Jean", address: { city: "Paris", country: "France" } }
198
210
  ]
199
- json = people.as_json :only => [:address, :city]
211
+ json = people.as_json only: [:address, :city]
200
212
  expected = [
201
- { 'address' => { 'city' => 'London' }},
202
- { 'address' => { 'city' => 'Paris' }}
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
- { :name => 'John', :address => { :city => 'London', :country => 'UK' }},
211
- { :name => 'Jean', :address => { :city => 'Paris' , :country => 'France' }}
222
+ { name: "John", address: { city: "London", country: "UK" } },
223
+ { name: "Jean", address: { city: "Paris", country: "France" } }
212
224
  ]
213
- json = people.to_json :only => [:address, :city]
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
- { :name => 'John', :address => { :city => 'London', :country => 'UK' }},
223
- { :name => 'Jean', :address => { :city => 'Paris' , :country => 'France' }}
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 :only => [:address, :city]
247
+ json = People.new.as_json only: [:address, :city]
236
248
  expected = [
237
- { 'address' => { 'city' => 'London' }},
238
- { 'address' => { 'city' => 'Paris' }}
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 :only => [:address, :city]
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 :only => [:address, :city]
262
+ json = People.new.each.as_json only: [:address, :city]
251
263
  expected = [
252
- { 'address' => { 'city' => 'London' }},
253
- { 'address' => { 'city' => 'Paris' }}
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 :only => [:address, :city]
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('UserNameAndEmail', :name, :email)
312
- Struct.new('UserNameAndDate', :name, :date)
313
- Struct.new('Custom', :name, :sub)
314
- user_email = Struct::UserNameAndEmail.new 'David', 'sample@example.com'
315
- user_birthday = Struct::UserNameAndDate.new 'David', Date.new(2010, 01, 01)
316
- custom = Struct::Custom.new 'David', user_birthday
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 nil.as_json
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['Eastern Time (US & Canada)']
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['Eastern Time (US & Canada)']
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['Eastern Time (US & Canada)']
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['Eastern Time (US & Canada)']
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::INFINITY }
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
- protected
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