json 1.8.3 → 2.3.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.
Files changed (82) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +2 -0
  3. data/.travis.yml +9 -11
  4. data/{CHANGES → CHANGES.md} +186 -90
  5. data/Gemfile +10 -6
  6. data/{COPYING-json-jruby → LICENSE} +5 -6
  7. data/{README-json-jruby.markdown → README-json-jruby.md} +0 -0
  8. data/{README.rdoc → README.md} +185 -134
  9. data/Rakefile +41 -40
  10. data/VERSION +1 -1
  11. data/ext/json/ext/fbuffer/fbuffer.h +0 -3
  12. data/ext/json/ext/generator/generator.c +142 -101
  13. data/ext/json/ext/generator/generator.h +7 -2
  14. data/ext/json/ext/parser/extconf.rb +3 -0
  15. data/ext/json/ext/parser/parser.c +383 -463
  16. data/ext/json/ext/parser/parser.h +4 -5
  17. data/ext/json/ext/parser/parser.rl +141 -184
  18. data/ext/json/extconf.rb +0 -1
  19. data/java/src/json/ext/ByteListTranscoder.java +1 -2
  20. data/java/src/json/ext/Generator.java +44 -22
  21. data/java/src/json/ext/GeneratorMethods.java +1 -2
  22. data/java/src/json/ext/GeneratorService.java +1 -2
  23. data/java/src/json/ext/GeneratorState.java +3 -56
  24. data/java/src/json/ext/OptionsReader.java +2 -3
  25. data/java/src/json/ext/Parser.java +132 -415
  26. data/java/src/json/ext/Parser.rl +48 -124
  27. data/java/src/json/ext/ParserService.java +1 -2
  28. data/java/src/json/ext/RuntimeInfo.java +1 -6
  29. data/java/src/json/ext/StringDecoder.java +1 -2
  30. data/java/src/json/ext/StringEncoder.java +5 -0
  31. data/java/src/json/ext/Utils.java +1 -2
  32. data/json-java.gemspec +16 -2
  33. data/json.gemspec +0 -0
  34. data/json_pure.gemspec +24 -26
  35. data/lib/json/add/bigdecimal.rb +3 -2
  36. data/lib/json/add/complex.rb +4 -3
  37. data/lib/json/add/core.rb +1 -0
  38. data/lib/json/add/date.rb +1 -1
  39. data/lib/json/add/date_time.rb +1 -1
  40. data/lib/json/add/exception.rb +1 -1
  41. data/lib/json/add/ostruct.rb +3 -3
  42. data/lib/json/add/range.rb +1 -1
  43. data/lib/json/add/rational.rb +3 -2
  44. data/lib/json/add/regexp.rb +3 -3
  45. data/lib/json/add/set.rb +29 -0
  46. data/lib/json/add/struct.rb +1 -1
  47. data/lib/json/add/symbol.rb +1 -1
  48. data/lib/json/add/time.rb +1 -1
  49. data/lib/json/common.rb +26 -54
  50. data/lib/json/ext.rb +0 -6
  51. data/lib/json/generic_object.rb +5 -4
  52. data/lib/json/pure/generator.rb +63 -126
  53. data/lib/json/pure/parser.rb +41 -81
  54. data/lib/json/pure.rb +2 -8
  55. data/lib/json/version.rb +2 -1
  56. data/lib/json.rb +1 -0
  57. data/references/rfc7159.txt +899 -0
  58. data/tests/fixtures/obsolete_fail1.json +1 -0
  59. data/tests/{test_json_addition.rb → json_addition_test.rb} +32 -25
  60. data/tests/json_common_interface_test.rb +126 -0
  61. data/tests/json_encoding_test.rb +107 -0
  62. data/tests/json_ext_parser_test.rb +15 -0
  63. data/tests/{test_json_fixtures.rb → json_fixtures_test.rb} +5 -8
  64. data/tests/{test_json_generate.rb → json_generator_test.rb} +123 -39
  65. data/tests/{test_json_generic_object.rb → json_generic_object_test.rb} +15 -8
  66. data/tests/json_parser_test.rb +472 -0
  67. data/tests/json_string_matching_test.rb +38 -0
  68. data/tests/{setup_variant.rb → test_helper.rb} +6 -0
  69. data/tools/diff.sh +18 -0
  70. data/tools/fuzz.rb +1 -9
  71. metadata +30 -47
  72. data/COPYING +0 -58
  73. data/GPL +0 -340
  74. data/TODO +0 -1
  75. data/data/example.json +0 -1
  76. data/data/index.html +0 -38
  77. data/data/prototype.js +0 -4184
  78. data/tests/fixtures/fail1.json +0 -1
  79. data/tests/test_json.rb +0 -553
  80. data/tests/test_json_encoding.rb +0 -65
  81. data/tests/test_json_string_matching.rb +0 -39
  82. data/tests/test_json_unicode.rb +0 -72
@@ -0,0 +1,29 @@
1
+ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
2
+ require 'json'
3
+ end
4
+ defined?(::Set) or require 'set'
5
+
6
+ class Set
7
+ # Import a JSON Marshalled object.
8
+ #
9
+ # method used for JSON marshalling support.
10
+ def self.json_create(object)
11
+ new object['a']
12
+ end
13
+
14
+ # Marshal the object to JSON.
15
+ #
16
+ # method used for JSON marshalling support.
17
+ def as_json(*)
18
+ {
19
+ JSON.create_id => self.class.name,
20
+ 'a' => to_a,
21
+ }
22
+ end
23
+
24
+ # return the JSON value
25
+ def to_json(*args)
26
+ as_json.to_json(*args)
27
+ end
28
+ end
29
+
@@ -1,8 +1,8 @@
1
+ #frozen_string_literal: false
1
2
  unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
2
3
  require 'json'
3
4
  end
4
5
 
5
- # Struct serialization/deserialization
6
6
  class Struct
7
7
 
8
8
  # Deserializes JSON string by constructing new Struct object with values
@@ -1,8 +1,8 @@
1
+ #frozen_string_literal: false
1
2
  unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
2
3
  require 'json'
3
4
  end
4
5
 
5
- # Symbol serialization/deserialization
6
6
  class Symbol
7
7
  # Returns a hash, that will be turned into a JSON object and represent this
8
8
  # object.
data/lib/json/add/time.rb CHANGED
@@ -1,8 +1,8 @@
1
+ #frozen_string_literal: false
1
2
  unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
2
3
  require 'json'
3
4
  end
4
5
 
5
- # Time serialization/deserialization
6
6
  class Time
7
7
 
8
8
  # Deserializes JSON string by converting time since epoch to Time
data/lib/json/common.rb CHANGED
@@ -1,14 +1,15 @@
1
+ #frozen_string_literal: false
1
2
  require 'json/version'
2
3
  require 'json/generic_object'
3
4
 
4
5
  module JSON
5
6
  class << self
6
- # If _object_ is string-like, parse the string and return the parsed result
7
- # as a Ruby data structure. Otherwise generate a JSON text from the Ruby
8
- # data structure object and return it.
7
+ # If _object_ is string-like, parse the string and return the parsed
8
+ # result as a Ruby data structure. Otherwise generate a JSON text from the
9
+ # Ruby data structure object and return it.
9
10
  #
10
- # The _opts_ argument is passed through to generate/parse respectively. See
11
- # generate and parse for their documentation.
11
+ # The _opts_ argument is passed through to generate/parse respectively.
12
+ # See generate and parse for their documentation.
12
13
  def [](object, opts = {})
13
14
  if object.respond_to? :to_str
14
15
  JSON.parse(object.to_str, opts)
@@ -24,7 +25,7 @@ module JSON
24
25
  # Set the JSON parser class _parser_ to be used by JSON.
25
26
  def parser=(parser) # :nodoc:
26
27
  @parser = parser
27
- remove_const :Parser if JSON.const_defined_in?(self, :Parser)
28
+ remove_const :Parser if const_defined?(:Parser, false)
28
29
  const_set :Parser, parser
29
30
  end
30
31
 
@@ -35,8 +36,8 @@ module JSON
35
36
  def deep_const_get(path) # :nodoc:
36
37
  path.to_s.split(/::/).inject(Object) do |p, c|
37
38
  case
38
- when c.empty? then p
39
- when JSON.const_defined_in?(p, c) then p.const_get(c)
39
+ when c.empty? then p
40
+ when p.const_defined?(c, true) then p.const_get(c)
40
41
  else
41
42
  begin
42
43
  p.const_missing(c)
@@ -138,10 +139,10 @@ module JSON
138
139
  # _opts_ can have the following
139
140
  # keys:
140
141
  # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
141
- # structures. Disable depth checking with :max_nesting => false. It defaults
142
- # to 100.
142
+ # structures. Disable depth checking with :max_nesting => false. It
143
+ # defaults to 100.
143
144
  # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
144
- # defiance of RFC 4627 to be parsed by the Parser. This option defaults
145
+ # defiance of RFC 7159 to be parsed by the Parser. This option defaults
145
146
  # to false.
146
147
  # * *symbolize_names*: If set to true, returns symbols for the names
147
148
  # (keys) in a JSON object. Otherwise strings are returned. Strings are
@@ -152,7 +153,7 @@ module JSON
152
153
  # * *object_class*: Defaults to Hash
153
154
  # * *array_class*: Defaults to Array
154
155
  def parse(source, opts = {})
155
- Parser.new(source, opts).parse
156
+ Parser.new(source, **(opts||{})).parse
156
157
  end
157
158
 
158
159
  # Parse the JSON document _source_ into a Ruby data structure and return it.
@@ -161,11 +162,11 @@ module JSON
161
162
  #
162
163
  # _opts_ can have the following keys:
163
164
  # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
164
- # structures. Enable depth checking with :max_nesting => anInteger. The parse!
165
- # methods defaults to not doing max depth checking: This can be dangerous
166
- # if someone wants to fill up your stack.
165
+ # structures. Enable depth checking with :max_nesting => anInteger. The
166
+ # parse! methods defaults to not doing max depth checking: This can be
167
+ # dangerous if someone wants to fill up your stack.
167
168
  # * *allow_nan*: If set to true, allow NaN, Infinity, and -Infinity in
168
- # defiance of RFC 4627 to be parsed by the Parser. This option defaults
169
+ # defiance of RFC 7159 to be parsed by the Parser. This option defaults
169
170
  # to true.
170
171
  # * *create_additions*: If set to false, the Parser doesn't create
171
172
  # additions even if a matching class and create_id was found. This option
@@ -174,8 +175,8 @@ module JSON
174
175
  opts = {
175
176
  :max_nesting => false,
176
177
  :allow_nan => true
177
- }.update(opts)
178
- Parser.new(source, opts).parse
178
+ }.merge(opts)
179
+ Parser.new(source, **(opts||{})).parse
179
180
  end
180
181
 
181
182
  # Generate a JSON document from the Ruby data structure _obj_ and return
@@ -295,13 +296,13 @@ module JSON
295
296
  # The global default options for the JSON.load method:
296
297
  # :max_nesting: false
297
298
  # :allow_nan: true
298
- # :quirks_mode: true
299
+ # :allow_blank: true
299
300
  attr_accessor :load_default_options
300
301
  end
301
302
  self.load_default_options = {
302
303
  :max_nesting => false,
303
304
  :allow_nan => true,
304
- :quirks_mode => true,
305
+ :allow_blank => true,
305
306
  :create_additions => true,
306
307
  }
307
308
 
@@ -328,7 +329,7 @@ module JSON
328
329
  elsif source.respond_to?(:read)
329
330
  source = source.read
330
331
  end
331
- if opts[:quirks_mode] && (source.nil? || source.empty?)
332
+ if opts[:allow_blank] && (source.nil? || source.empty?)
332
333
  source = 'null'
333
334
  end
334
335
  result = parse(source, opts)
@@ -357,13 +358,12 @@ module JSON
357
358
  # The global default options for the JSON.dump method:
358
359
  # :max_nesting: false
359
360
  # :allow_nan: true
360
- # :quirks_mode: true
361
+ # :allow_blank: true
361
362
  attr_accessor :dump_default_options
362
363
  end
363
364
  self.dump_default_options = {
364
365
  :max_nesting => false,
365
366
  :allow_nan => true,
366
- :quirks_mode => true,
367
367
  }
368
368
 
369
369
  # Dumps _obj_ as a JSON string, i.e. calls generate on the object and returns
@@ -402,37 +402,9 @@ module JSON
402
402
  raise ArgumentError, "exceed depth limit"
403
403
  end
404
404
 
405
- # Swap consecutive bytes of _string_ in place.
406
- def self.swap!(string) # :nodoc:
407
- 0.upto(string.size / 2) do |i|
408
- break unless string[2 * i + 1]
409
- string[2 * i], string[2 * i + 1] = string[2 * i + 1], string[2 * i]
410
- end
411
- string
412
- end
413
-
414
- # Shortcut for iconv.
415
- if ::String.method_defined?(:encode)
416
- # Encodes string using Ruby's _String.encode_
417
- def self.iconv(to, from, string)
418
- string.encode(to, from)
419
- end
420
- else
421
- require 'iconv'
422
- # Encodes string using _iconv_ library
423
- def self.iconv(to, from, string)
424
- Iconv.conv(to, from, string)
425
- end
426
- end
427
-
428
- if ::Object.method(:const_defined?).arity == 1
429
- def self.const_defined_in?(modul, constant)
430
- modul.const_defined?(constant)
431
- end
432
- else
433
- def self.const_defined_in?(modul, constant)
434
- modul.const_defined?(constant, false)
435
- end
405
+ # Encodes string using Ruby's _String.encode_
406
+ def self.iconv(to, from, string)
407
+ string.encode(to, from)
436
408
  end
437
409
  end
438
410
 
data/lib/json/ext.rb CHANGED
@@ -1,9 +1,3 @@
1
- if ENV['SIMPLECOV_COVERAGE'].to_i == 1
2
- require 'simplecov'
3
- SimpleCov.start do
4
- add_filter "/tests/"
5
- end
6
- end
7
1
  require 'json/common'
8
2
 
9
3
  module JSON
@@ -1,3 +1,4 @@
1
+ #frozen_string_literal: false
1
2
  require 'ostruct'
2
3
 
3
4
  module JSON
@@ -48,12 +49,12 @@ module JSON
48
49
  end
49
50
 
50
51
  def [](name)
51
- table[name.to_sym]
52
- end
52
+ __send__(name)
53
+ end unless method_defined?(:[])
53
54
 
54
55
  def []=(name, value)
55
- __send__ "#{name}=", value
56
- end
56
+ __send__("#{name}=", value)
57
+ end unless method_defined?(:[]=)
57
58
 
58
59
  def |(other)
59
60
  self.class[other.to_hash.merge(to_hash)]
@@ -1,3 +1,4 @@
1
+ #frozen_string_literal: false
1
2
  module JSON
2
3
  MAP = {
3
4
  "\x0" => '\u0000',
@@ -38,85 +39,45 @@ module JSON
38
39
 
39
40
  # Convert a UTF8 encoded Ruby string _string_ to a JSON string, encoded with
40
41
  # UTF16 big endian characters as \u????, and return it.
41
- if defined?(::Encoding)
42
- def utf8_to_json(string) # :nodoc:
43
- string = string.dup
44
- string.force_encoding(::Encoding::ASCII_8BIT)
45
- string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] }
46
- string.force_encoding(::Encoding::UTF_8)
47
- string
48
- end
49
-
50
- def utf8_to_json_ascii(string) # :nodoc:
51
- string = string.dup
52
- string.force_encoding(::Encoding::ASCII_8BIT)
53
- string.gsub!(/["\\\x0-\x1f]/n) { MAP[$&] }
54
- string.gsub!(/(
55
- (?:
56
- [\xc2-\xdf][\x80-\xbf] |
57
- [\xe0-\xef][\x80-\xbf]{2} |
58
- [\xf0-\xf4][\x80-\xbf]{3}
59
- )+ |
60
- [\x80-\xc1\xf5-\xff] # invalid
61
- )/nx) { |c|
62
- c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
63
- s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0]
64
- s.force_encoding(::Encoding::ASCII_8BIT)
65
- s.gsub!(/.{4}/n, '\\\\u\&')
66
- s.force_encoding(::Encoding::UTF_8)
67
- }
68
- string.force_encoding(::Encoding::UTF_8)
69
- string
70
- rescue => e
71
- raise GeneratorError.wrap(e)
72
- end
73
-
74
- def valid_utf8?(string)
75
- encoding = string.encoding
76
- (encoding == Encoding::UTF_8 || encoding == Encoding::ASCII) &&
77
- string.valid_encoding?
78
- end
79
- module_function :valid_utf8?
80
- else
81
- def utf8_to_json(string) # :nodoc:
82
- string.gsub(/["\\\x0-\x1f]/n) { MAP[$&] }
83
- end
42
+ def utf8_to_json(string) # :nodoc:
43
+ string = string.dup
44
+ string.force_encoding(::Encoding::ASCII_8BIT)
45
+ string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] }
46
+ string.force_encoding(::Encoding::UTF_8)
47
+ string
48
+ end
84
49
 
85
- def utf8_to_json_ascii(string) # :nodoc:
86
- string = string.gsub(/["\\\x0-\x1f]/) { MAP[$&] }
87
- string.gsub!(/(
88
- (?:
89
- [\xc2-\xdf][\x80-\xbf] |
90
- [\xe0-\xef][\x80-\xbf]{2} |
91
- [\xf0-\xf4][\x80-\xbf]{3}
92
- )+ |
93
- [\x80-\xc1\xf5-\xff] # invalid
94
- )/nx) { |c|
95
- c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
96
- s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0]
97
- s.gsub!(/.{4}/n, '\\\\u\&')
98
- }
99
- string
100
- rescue => e
101
- raise GeneratorError.wrap(e)
102
- end
50
+ def utf8_to_json_ascii(string) # :nodoc:
51
+ string = string.dup
52
+ string.force_encoding(::Encoding::ASCII_8BIT)
53
+ string.gsub!(/["\\\x0-\x1f]/n) { MAP[$&] }
54
+ string.gsub!(/(
55
+ (?:
56
+ [\xc2-\xdf][\x80-\xbf] |
57
+ [\xe0-\xef][\x80-\xbf]{2} |
58
+ [\xf0-\xf4][\x80-\xbf]{3}
59
+ )+ |
60
+ [\x80-\xc1\xf5-\xff] # invalid
61
+ )/nx) { |c|
62
+ c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
63
+ s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0]
64
+ s.force_encoding(::Encoding::ASCII_8BIT)
65
+ s.gsub!(/.{4}/n, '\\\\u\&')
66
+ s.force_encoding(::Encoding::UTF_8)
67
+ }
68
+ string.force_encoding(::Encoding::UTF_8)
69
+ string
70
+ rescue => e
71
+ raise GeneratorError.wrap(e)
72
+ end
103
73
 
104
- def valid_utf8?(string)
105
- string =~
106
- /\A( [\x09\x0a\x0d\x20-\x7e] # ASCII
107
- | [\xc2-\xdf][\x80-\xbf] # non-overlong 2-byte
108
- | \xe0[\xa0-\xbf][\x80-\xbf] # excluding overlongs
109
- | [\xe1-\xec\xee\xef][\x80-\xbf]{2} # straight 3-byte
110
- | \xed[\x80-\x9f][\x80-\xbf] # excluding surrogates
111
- | \xf0[\x90-\xbf][\x80-\xbf]{2} # planes 1-3
112
- | [\xf1-\xf3][\x80-\xbf]{3} # planes 4-15
113
- | \xf4[\x80-\x8f][\x80-\xbf]{2} # plane 16
114
- )*\z/nx
115
- end
74
+ def valid_utf8?(string)
75
+ encoding = string.encoding
76
+ (encoding == Encoding::UTF_8 || encoding == Encoding::ASCII) &&
77
+ string.valid_encoding?
116
78
  end
117
79
  module_function :utf8_to_json, :utf8_to_json_ascii, :valid_utf8?
118
80
 
119
-
120
81
  module Pure
121
82
  module Generator
122
83
  # This class is used to create State instances, that are use to hold data
@@ -154,8 +115,6 @@ module JSON
154
115
  # * *allow_nan*: true if NaN, Infinity, and -Infinity should be
155
116
  # generated, otherwise an exception is thrown, if these values are
156
117
  # encountered. This options defaults to false.
157
- # * *quirks_mode*: Enables quirks_mode for parser, that is for example
158
- # generating single JSON values instead of documents is possible.
159
118
  def initialize(opts = {})
160
119
  @indent = ''
161
120
  @space = ''
@@ -164,7 +123,6 @@ module JSON
164
123
  @array_nl = ''
165
124
  @allow_nan = false
166
125
  @ascii_only = false
167
- @quirks_mode = false
168
126
  @buffer_initial_length = 1024
169
127
  configure opts
170
128
  end
@@ -190,10 +148,6 @@ module JSON
190
148
  # the generated JSON, max_nesting = 0 if no maximum is checked.
191
149
  attr_accessor :max_nesting
192
150
 
193
- # If this attribute is set to true, quirks mode is enabled, otherwise
194
- # it's disabled.
195
- attr_accessor :quirks_mode
196
-
197
151
  # :stopdoc:
198
152
  attr_reader :buffer_initial_length
199
153
 
@@ -233,11 +187,6 @@ module JSON
233
187
  @ascii_only
234
188
  end
235
189
 
236
- # Returns true, if quirks mode is enabled. Otherwise returns false.
237
- def quirks_mode?
238
- @quirks_mode
239
- end
240
-
241
190
  # Configure this State instance with the Hash _opts_, and return
242
191
  # itself.
243
192
  def configure(opts)
@@ -259,7 +208,6 @@ module JSON
259
208
  @allow_nan = !!opts[:allow_nan] if opts.key?(:allow_nan)
260
209
  @ascii_only = opts[:ascii_only] if opts.key?(:ascii_only)
261
210
  @depth = opts[:depth] || 0
262
- @quirks_mode = opts[:quirks_mode] if opts.key?(:quirks_mode)
263
211
  @buffer_initial_length ||= opts[:buffer_initial_length]
264
212
 
265
213
  if !opts.key?(:max_nesting) # defaults to 100
@@ -286,20 +234,14 @@ module JSON
286
234
 
287
235
  alias to_hash to_h
288
236
 
289
- # Generates a valid JSON document from object +obj+ and returns the
290
- # result. If no valid JSON document can be created this method raises a
237
+ # Generates a valid JSON document from object +obj+ and
238
+ # returns the result. If no valid JSON document can be
239
+ # created this method raises a
291
240
  # GeneratorError exception.
292
241
  def generate(obj)
293
242
  result = obj.to_json(self)
294
243
  JSON.valid_utf8?(result) or raise GeneratorError,
295
244
  "source sequence #{result.inspect} is illegal/malformed utf-8"
296
- unless @quirks_mode
297
- unless result =~ /\A\s*\[/ && result =~ /\]\s*\Z/ ||
298
- result =~ /\A\s*\{/ && result =~ /\}\s*\Z/
299
- then
300
- raise GeneratorError, "only generation of JSON objects or arrays allowed"
301
- end
302
- end
303
245
  result
304
246
  end
305
247
 
@@ -308,7 +250,8 @@ module JSON
308
250
  if respond_to?(name)
309
251
  __send__(name)
310
252
  else
311
- instance_variable_get("@#{name}")
253
+ instance_variable_get("@#{name}") if
254
+ instance_variables.include?("@#{name}".to_sym) # avoid warning
312
255
  end
313
256
  end
314
257
 
@@ -363,7 +306,11 @@ module JSON
363
306
  result << state.space_before
364
307
  result << ':'
365
308
  result << state.space
366
- result << value.to_json(state)
309
+ if value.respond_to?(:to_json)
310
+ result << value.to_json(state)
311
+ else
312
+ result << %{"#{String(value)}"}
313
+ end
367
314
  first = false
368
315
  }
369
316
  depth = state.depth -= 1
@@ -398,7 +345,11 @@ module JSON
398
345
  each { |value|
399
346
  result << delim unless first
400
347
  result << state.indent * depth if indent
401
- result << value.to_json(state)
348
+ if value.respond_to?(:to_json)
349
+ result << value.to_json(state)
350
+ else
351
+ result << %{"#{String(value)}"}
352
+ end
402
353
  first = false
403
354
  }
404
355
  depth = state.depth -= 1
@@ -437,34 +388,20 @@ module JSON
437
388
  end
438
389
 
439
390
  module String
440
- if defined?(::Encoding)
441
- # This string should be encoded with UTF-8 A call to this method
442
- # returns a JSON string encoded with UTF16 big endian characters as
443
- # \u????.
444
- def to_json(state = nil, *args)
445
- state = State.from_state(state)
446
- if encoding == ::Encoding::UTF_8
447
- string = self
448
- else
449
- string = encode(::Encoding::UTF_8)
450
- end
451
- if state.ascii_only?
452
- '"' << JSON.utf8_to_json_ascii(string) << '"'
453
- else
454
- '"' << JSON.utf8_to_json(string) << '"'
455
- end
391
+ # This string should be encoded with UTF-8 A call to this method
392
+ # returns a JSON string encoded with UTF16 big endian characters as
393
+ # \u????.
394
+ def to_json(state = nil, *args)
395
+ state = State.from_state(state)
396
+ if encoding == ::Encoding::UTF_8
397
+ string = self
398
+ else
399
+ string = encode(::Encoding::UTF_8)
456
400
  end
457
- else
458
- # This string should be encoded with UTF-8 A call to this method
459
- # returns a JSON string encoded with UTF16 big endian characters as
460
- # \u????.
461
- def to_json(state = nil, *args)
462
- state = State.from_state(state)
463
- if state.ascii_only?
464
- '"' << JSON.utf8_to_json_ascii(self) << '"'
465
- else
466
- '"' << JSON.utf8_to_json(self) << '"'
467
- end
401
+ if state.ascii_only?
402
+ '"' << JSON.utf8_to_json_ascii(string) << '"'
403
+ else
404
+ '"' << JSON.utf8_to_json(string) << '"'
468
405
  end
469
406
  end
470
407