json 2.6.3 → 2.7.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,14 +4,28 @@ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
4
4
  end
5
5
 
6
6
  class Rational
7
- # Deserializes JSON string by converting numerator value <tt>n</tt>,
8
- # denominator value <tt>d</tt>, to a Rational object.
7
+
8
+ # See #as_json.
9
9
  def self.json_create(object)
10
10
  Rational(object['n'], object['d'])
11
11
  end
12
12
 
13
- # Returns a hash, that will be turned into a JSON object and represent this
14
- # object.
13
+ # Methods <tt>Rational#as_json</tt> and +Rational.json_create+ may be used
14
+ # to serialize and deserialize a \Rational object;
15
+ # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
16
+ #
17
+ # \Method <tt>Rational#as_json</tt> serializes +self+,
18
+ # returning a 2-element hash representing +self+:
19
+ #
20
+ # require 'json/add/rational'
21
+ # x = Rational(2, 3).as_json
22
+ # # => {"json_class"=>"Rational", "n"=>2, "d"=>3}
23
+ #
24
+ # \Method +JSON.create+ deserializes such a hash, returning a \Rational object:
25
+ #
26
+ # Rational.json_create(x)
27
+ # # => (2/3)
28
+ #
15
29
  def as_json(*)
16
30
  {
17
31
  JSON.create_id => self.class.name,
@@ -20,7 +34,15 @@ class Rational
20
34
  }
21
35
  end
22
36
 
23
- # Stores class name (Rational) along with numerator value <tt>n</tt> and denominator value <tt>d</tt> as JSON string
37
+ # Returns a JSON string representing +self+:
38
+ #
39
+ # require 'json/add/rational'
40
+ # puts Rational(2, 3).to_json
41
+ #
42
+ # Output:
43
+ #
44
+ # {"json_class":"Rational","n":2,"d":3}
45
+ #
24
46
  def to_json(*args)
25
47
  as_json.to_json(*args)
26
48
  end
@@ -5,15 +5,26 @@ end
5
5
 
6
6
  class Regexp
7
7
 
8
- # Deserializes JSON string by constructing new Regexp object with source
9
- # <tt>s</tt> (Regexp or String) and options <tt>o</tt> serialized by
10
- # <tt>to_json</tt>
8
+ # See #as_json.
11
9
  def self.json_create(object)
12
10
  new(object['s'], object['o'])
13
11
  end
14
12
 
15
- # Returns a hash, that will be turned into a JSON object and represent this
16
- # object.
13
+ # Methods <tt>Regexp#as_json</tt> and +Regexp.json_create+ may be used
14
+ # to serialize and deserialize a \Regexp object;
15
+ # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
16
+ #
17
+ # \Method <tt>Regexp#as_json</tt> serializes +self+,
18
+ # returning a 2-element hash representing +self+:
19
+ #
20
+ # require 'json/add/regexp'
21
+ # x = /foo/.as_json
22
+ # # => {"json_class"=>"Regexp", "o"=>0, "s"=>"foo"}
23
+ #
24
+ # \Method +JSON.create+ deserializes such a hash, returning a \Regexp object:
25
+ #
26
+ # Regexp.json_create(x) # => /foo/
27
+ #
17
28
  def as_json(*)
18
29
  {
19
30
  JSON.create_id => self.class.name,
@@ -22,8 +33,15 @@ class Regexp
22
33
  }
23
34
  end
24
35
 
25
- # Stores class name (Regexp) with options <tt>o</tt> and source <tt>s</tt>
26
- # (Regexp or String) as JSON string
36
+ # Returns a JSON string representing +self+:
37
+ #
38
+ # require 'json/add/regexp'
39
+ # puts /foo/.to_json
40
+ #
41
+ # Output:
42
+ #
43
+ # {"json_class":"Regexp","o":0,"s":"foo"}
44
+ #
27
45
  def to_json(*args)
28
46
  as_json.to_json(*args)
29
47
  end
data/lib/json/add/set.rb CHANGED
@@ -4,16 +4,27 @@ end
4
4
  defined?(::Set) or require 'set'
5
5
 
6
6
  class Set
7
- # Import a JSON Marshalled object.
8
- #
9
- # method used for JSON marshalling support.
7
+
8
+ # See #as_json.
10
9
  def self.json_create(object)
11
10
  new object['a']
12
11
  end
13
12
 
14
- # Marshal the object to JSON.
13
+ # Methods <tt>Set#as_json</tt> and +Set.json_create+ may be used
14
+ # to serialize and deserialize a \Set object;
15
+ # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
16
+ #
17
+ # \Method <tt>Set#as_json</tt> serializes +self+,
18
+ # returning a 2-element hash representing +self+:
19
+ #
20
+ # require 'json/add/set'
21
+ # x = Set.new(%w/foo bar baz/).as_json
22
+ # # => {"json_class"=>"Set", "a"=>["foo", "bar", "baz"]}
23
+ #
24
+ # \Method +JSON.create+ deserializes such a hash, returning a \Set object:
25
+ #
26
+ # Set.json_create(x) # => #<Set: {"foo", "bar", "baz"}>
15
27
  #
16
- # method used for JSON marshalling support.
17
28
  def as_json(*)
18
29
  {
19
30
  JSON.create_id => self.class.name,
@@ -21,7 +32,15 @@ class Set
21
32
  }
22
33
  end
23
34
 
24
- # return the JSON value
35
+ # Returns a JSON string representing +self+:
36
+ #
37
+ # require 'json/add/set'
38
+ # puts Set.new(%w/foo bar baz/).to_json
39
+ #
40
+ # Output:
41
+ #
42
+ # {"json_class":"Set","a":["foo","bar","baz"]}
43
+ #
25
44
  def to_json(*args)
26
45
  as_json.to_json(*args)
27
46
  end
@@ -5,14 +5,28 @@ end
5
5
 
6
6
  class Struct
7
7
 
8
- # Deserializes JSON string by constructing new Struct object with values
9
- # <tt>v</tt> serialized by <tt>to_json</tt>.
8
+ # See #as_json.
10
9
  def self.json_create(object)
11
10
  new(*object['v'])
12
11
  end
13
12
 
14
- # Returns a hash, that will be turned into a JSON object and represent this
15
- # object.
13
+ # Methods <tt>Struct#as_json</tt> and +Struct.json_create+ may be used
14
+ # to serialize and deserialize a \Struct object;
15
+ # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
16
+ #
17
+ # \Method <tt>Struct#as_json</tt> serializes +self+,
18
+ # returning a 2-element hash representing +self+:
19
+ #
20
+ # require 'json/add/struct'
21
+ # Customer = Struct.new('Customer', :name, :address, :zip)
22
+ # x = Struct::Customer.new.as_json
23
+ # # => {"json_class"=>"Struct::Customer", "v"=>[nil, nil, nil]}
24
+ #
25
+ # \Method +JSON.create+ deserializes such a hash, returning a \Struct object:
26
+ #
27
+ # Struct::Customer.json_create(x)
28
+ # # => #<struct Struct::Customer name=nil, address=nil, zip=nil>
29
+ #
16
30
  def as_json(*)
17
31
  klass = self.class.name
18
32
  klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!"
@@ -22,8 +36,16 @@ class Struct
22
36
  }
23
37
  end
24
38
 
25
- # Stores class name (Struct) with Struct values <tt>v</tt> as a JSON string.
26
- # Only named structs are supported.
39
+ # Returns a JSON string representing +self+:
40
+ #
41
+ # require 'json/add/struct'
42
+ # Customer = Struct.new('Customer', :name, :address, :zip)
43
+ # puts Struct::Customer.new.to_json
44
+ #
45
+ # Output:
46
+ #
47
+ # {"json_class":"Struct","t":{'name':'Rowdy',"age":null}}
48
+ #
27
49
  def to_json(*args)
28
50
  as_json.to_json(*args)
29
51
  end
@@ -1,11 +1,26 @@
1
+
1
2
  #frozen_string_literal: false
2
3
  unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
3
4
  require 'json'
4
5
  end
5
6
 
6
7
  class Symbol
7
- # Returns a hash, that will be turned into a JSON object and represent this
8
- # object.
8
+
9
+ # Methods <tt>Symbol#as_json</tt> and +Symbol.json_create+ may be used
10
+ # to serialize and deserialize a \Symbol object;
11
+ # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
12
+ #
13
+ # \Method <tt>Symbol#as_json</tt> serializes +self+,
14
+ # returning a 2-element hash representing +self+:
15
+ #
16
+ # require 'json/add/symbol'
17
+ # x = :foo.as_json
18
+ # # => {"json_class"=>"Symbol", "s"=>"foo"}
19
+ #
20
+ # \Method +JSON.create+ deserializes such a hash, returning a \Symbol object:
21
+ #
22
+ # Symbol.json_create(x) # => :foo
23
+ #
9
24
  def as_json(*)
10
25
  {
11
26
  JSON.create_id => self.class.name,
@@ -13,12 +28,20 @@ class Symbol
13
28
  }
14
29
  end
15
30
 
16
- # Stores class name (Symbol) with String representation of Symbol as a JSON string.
31
+ # Returns a JSON string representing +self+:
32
+ #
33
+ # require 'json/add/symbol'
34
+ # puts :foo.to_json
35
+ #
36
+ # Output:
37
+ #
38
+ # # {"json_class":"Symbol","s":"foo"}
39
+ #
17
40
  def to_json(*a)
18
41
  as_json.to_json(*a)
19
42
  end
20
43
 
21
- # Deserializes JSON string by converting the <tt>string</tt> value stored in the object to a Symbol
44
+ # See #as_json.
22
45
  def self.json_create(o)
23
46
  o['s'].to_sym
24
47
  end
data/lib/json/add/time.rb CHANGED
@@ -5,7 +5,7 @@ end
5
5
 
6
6
  class Time
7
7
 
8
- # Deserializes JSON string by converting time since epoch to Time
8
+ # See #as_json.
9
9
  def self.json_create(object)
10
10
  if usec = object.delete('u') # used to be tv_usec -> tv_nsec
11
11
  object['n'] = usec * 1000
@@ -17,8 +17,22 @@ class Time
17
17
  end
18
18
  end
19
19
 
20
- # Returns a hash, that will be turned into a JSON object and represent this
21
- # object.
20
+ # Methods <tt>Time#as_json</tt> and +Time.json_create+ may be used
21
+ # to serialize and deserialize a \Time object;
22
+ # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
23
+ #
24
+ # \Method <tt>Time#as_json</tt> serializes +self+,
25
+ # returning a 2-element hash representing +self+:
26
+ #
27
+ # require 'json/add/time'
28
+ # x = Time.now.as_json
29
+ # # => {"json_class"=>"Time", "s"=>1700931656, "n"=>472846644}
30
+ #
31
+ # \Method +JSON.create+ deserializes such a hash, returning a \Time object:
32
+ #
33
+ # Time.json_create(x)
34
+ # # => 2023-11-25 11:00:56.472846644 -0600
35
+ #
22
36
  def as_json(*)
23
37
  nanoseconds = [ tv_usec * 1000 ]
24
38
  respond_to?(:tv_nsec) and nanoseconds << tv_nsec
@@ -30,8 +44,15 @@ class Time
30
44
  }
31
45
  end
32
46
 
33
- # Stores class name (Time) with number of seconds since epoch and number of
34
- # microseconds for Time as JSON string
47
+ # Returns a JSON string representing +self+:
48
+ #
49
+ # require 'json/add/time'
50
+ # puts Time.now.to_json
51
+ #
52
+ # Output:
53
+ #
54
+ # {"json_class":"Time","s":1700931678,"n":980650786}
55
+ #
35
56
  def to_json(*args)
36
57
  as_json.to_json(*args)
37
58
  end
data/lib/json/common.rb CHANGED
@@ -1,8 +1,12 @@
1
1
  #frozen_string_literal: false
2
2
  require 'json/version'
3
- require 'json/generic_object'
4
3
 
5
4
  module JSON
5
+ autoload :GenericObject, 'json/generic_object'
6
+
7
+ NOT_SET = Object.new.freeze
8
+ private_constant :NOT_SET
9
+
6
10
  class << self
7
11
  # :call-seq:
8
12
  # JSON[object] -> new_array or new_string
@@ -295,19 +299,9 @@ module JSON
295
299
  #
296
300
  def generate(obj, opts = nil)
297
301
  if State === opts
298
- state, opts = opts, nil
302
+ state = opts
299
303
  else
300
- state = State.new
301
- end
302
- if opts
303
- if opts.respond_to? :to_hash
304
- opts = opts.to_hash
305
- elsif opts.respond_to? :to_h
306
- opts = opts.to_h
307
- else
308
- raise TypeError, "can't convert #{opts.class} into Hash"
309
- end
310
- state = state.configure(opts)
304
+ state = State.new(opts)
311
305
  end
312
306
  state.generate(obj)
313
307
  end
@@ -334,19 +328,9 @@ module JSON
334
328
  # JSON.fast_generate(a)
335
329
  def fast_generate(obj, opts = nil)
336
330
  if State === opts
337
- state, opts = opts, nil
331
+ state = opts
338
332
  else
339
- state = JSON.create_fast_state
340
- end
341
- if opts
342
- if opts.respond_to? :to_hash
343
- opts = opts.to_hash
344
- elsif opts.respond_to? :to_h
345
- opts = opts.to_h
346
- else
347
- raise TypeError, "can't convert #{opts.class} into Hash"
348
- end
349
- state.configure(opts)
333
+ state = JSON.create_fast_state.configure(opts)
350
334
  end
351
335
  state.generate(obj)
352
336
  end
@@ -592,13 +576,13 @@ module JSON
592
576
  # Sets or returns the default options for the JSON.dump method.
593
577
  # Initially:
594
578
  # opts = JSON.dump_default_options
595
- # opts # => {:max_nesting=>false, :allow_nan=>true, :escape_slash=>false}
579
+ # opts # => {:max_nesting=>false, :allow_nan=>true, :script_safe=>false}
596
580
  attr_accessor :dump_default_options
597
581
  end
598
582
  self.dump_default_options = {
599
583
  :max_nesting => false,
600
584
  :allow_nan => true,
601
- :escape_slash => false,
585
+ :script_safe => false,
602
586
  }
603
587
 
604
588
  # :call-seq:
@@ -628,16 +612,18 @@ module JSON
628
612
  # puts File.read(path)
629
613
  # Output:
630
614
  # {"foo":[0,1],"bar":{"baz":2,"bat":3},"bam":"bad"}
631
- def dump(obj, anIO = nil, limit = nil)
632
- if anIO and limit.nil?
633
- anIO = anIO.to_io if anIO.respond_to?(:to_io)
634
- unless anIO.respond_to?(:write)
635
- limit = anIO
636
- anIO = nil
637
- end
615
+ def dump(obj, anIO = nil, limit = nil, kwargs = nil)
616
+ io_limit_opt = [anIO, limit, kwargs].compact
617
+ kwargs = io_limit_opt.pop if io_limit_opt.last.is_a?(Hash)
618
+ anIO, limit = io_limit_opt
619
+ if anIO.respond_to?(:to_io)
620
+ anIO = anIO.to_io
621
+ elsif limit.nil? && !anIO.respond_to?(:write)
622
+ anIO, limit = nil, anIO
638
623
  end
639
624
  opts = JSON.dump_default_options
640
625
  opts = opts.merge(:max_nesting => limit) if limit
626
+ opts = merge_dump_options(opts, **kwargs) if kwargs
641
627
  result = generate(obj, opts)
642
628
  if anIO
643
629
  anIO.write result
@@ -653,6 +639,15 @@ module JSON
653
639
  def self.iconv(to, from, string)
654
640
  string.encode(to, from)
655
641
  end
642
+
643
+ def merge_dump_options(opts, strict: NOT_SET)
644
+ opts = opts.merge(strict: strict) if NOT_SET != strict
645
+ opts
646
+ end
647
+
648
+ class << self
649
+ private :merge_dump_options
650
+ end
656
651
  end
657
652
 
658
653
  module ::Kernel
@@ -1,5 +1,9 @@
1
1
  #frozen_string_literal: false
2
- require 'ostruct'
2
+ begin
3
+ require 'ostruct'
4
+ rescue LoadError
5
+ warn "JSON::GenericObject requires 'ostruct'. Please install it with `gem install ostruct`."
6
+ end
3
7
 
4
8
  module JSON
5
9
  class GenericObject < OpenStruct
@@ -67,5 +71,5 @@ module JSON
67
71
  def to_json(*a)
68
72
  as_json.to_json(*a)
69
73
  end
70
- end
74
+ end if defined?(::OpenStruct)
71
75
  end
@@ -37,25 +37,34 @@ module JSON
37
37
  '\\' => '\\\\',
38
38
  } # :nodoc:
39
39
 
40
- ESCAPE_SLASH_MAP = MAP.merge(
40
+ ESCAPE_PATTERN = /[\/"\\\x0-\x1f]/n # :nodoc:
41
+
42
+ SCRIPT_SAFE_MAP = MAP.merge(
41
43
  '/' => '\\/',
44
+ "\u2028".b => '\u2028',
45
+ "\u2029".b => '\u2029',
42
46
  )
43
47
 
48
+ SCRIPT_SAFE_ESCAPE_PATTERN = Regexp.union(ESCAPE_PATTERN, "\u2028".b, "\u2029".b)
49
+
44
50
  # Convert a UTF8 encoded Ruby string _string_ to a JSON string, encoded with
45
51
  # UTF16 big endian characters as \u????, and return it.
46
- def utf8_to_json(string, escape_slash = false) # :nodoc:
52
+ def utf8_to_json(string, script_safe = false) # :nodoc:
47
53
  string = string.dup
48
54
  string.force_encoding(::Encoding::ASCII_8BIT)
49
- map = escape_slash ? ESCAPE_SLASH_MAP : MAP
50
- string.gsub!(/[\/"\\\x0-\x1f]/) { map[$&] || $& }
55
+ if script_safe
56
+ string.gsub!(SCRIPT_SAFE_ESCAPE_PATTERN) { SCRIPT_SAFE_MAP[$&] || $& }
57
+ else
58
+ string.gsub!(ESCAPE_PATTERN) { MAP[$&] || $& }
59
+ end
51
60
  string.force_encoding(::Encoding::UTF_8)
52
61
  string
53
62
  end
54
63
 
55
- def utf8_to_json_ascii(string, escape_slash = false) # :nodoc:
64
+ def utf8_to_json_ascii(string, script_safe = false) # :nodoc:
56
65
  string = string.dup
57
66
  string.force_encoding(::Encoding::ASCII_8BIT)
58
- map = escape_slash ? ESCAPE_SLASH_MAP : MAP
67
+ map = script_safe ? SCRIPT_SAFE_MAP : MAP
59
68
  string.gsub!(/[\/"\\\x0-\x1f]/n) { map[$&] || $& }
60
69
  string.gsub!(/(
61
70
  (?:
@@ -115,7 +124,8 @@ module JSON
115
124
  # * *space_before*: a string that is put before a : pair delimiter (default: ''),
116
125
  # * *object_nl*: a string that is put at the end of a JSON object (default: ''),
117
126
  # * *array_nl*: a string that is put at the end of a JSON array (default: ''),
118
- # * *escape_slash*: true if forward slash (/) should be escaped (default: false)
127
+ # * *script_safe*: true if U+2028, U+2029 and forward slash (/) should be escaped
128
+ # as to make the JSON object safe to interpolate in a script tag (default: false).
119
129
  # * *check_circular*: is deprecated now, use the :max_nesting option instead,
120
130
  # * *max_nesting*: sets the maximum level of data structure nesting in
121
131
  # the generated JSON, max_nesting = 0 if no maximum should be checked.
@@ -130,7 +140,8 @@ module JSON
130
140
  @array_nl = ''
131
141
  @allow_nan = false
132
142
  @ascii_only = false
133
- @escape_slash = false
143
+ @script_safe = false
144
+ @strict = false
134
145
  @buffer_initial_length = 1024
135
146
  configure opts
136
147
  end
@@ -158,7 +169,11 @@ module JSON
158
169
 
159
170
  # If this attribute is set to true, forward slashes will be escaped in
160
171
  # all json strings.
161
- attr_accessor :escape_slash
172
+ attr_accessor :script_safe
173
+
174
+ # If this attribute is set to true, attempting to serialize types not
175
+ # supported by the JSON spec will raise a JSON::GeneratorError
176
+ attr_accessor :strict
162
177
 
163
178
  # :stopdoc:
164
179
  attr_reader :buffer_initial_length
@@ -200,8 +215,13 @@ module JSON
200
215
  end
201
216
 
202
217
  # Returns true, if forward slashes are escaped. Otherwise returns false.
203
- def escape_slash?
204
- @escape_slash
218
+ def script_safe?
219
+ @script_safe
220
+ end
221
+
222
+ # Returns true, if forward slashes are escaped. Otherwise returns false.
223
+ def strict?
224
+ @strict
205
225
  end
206
226
 
207
227
  # Configure this State instance with the Hash _opts_, and return
@@ -214,7 +234,7 @@ module JSON
214
234
  else
215
235
  raise TypeError, "can't convert #{opts.class} into Hash"
216
236
  end
217
- for key, value in opts
237
+ opts.each do |key, value|
218
238
  instance_variable_set "@#{key}", value
219
239
  end
220
240
  @indent = opts[:indent] if opts.key?(:indent)
@@ -226,7 +246,16 @@ module JSON
226
246
  @ascii_only = opts[:ascii_only] if opts.key?(:ascii_only)
227
247
  @depth = opts[:depth] || 0
228
248
  @buffer_initial_length ||= opts[:buffer_initial_length]
229
- @escape_slash = !!opts[:escape_slash] if opts.key?(:escape_slash)
249
+
250
+ @script_safe = if opts.key?(:script_safe)
251
+ !!opts[:script_safe]
252
+ elsif opts.key?(:escape_slash)
253
+ !!opts[:escape_slash]
254
+ else
255
+ false
256
+ end
257
+
258
+ @strict = !!opts[:strict] if opts.key?(:strict)
230
259
 
231
260
  if !opts.key?(:max_nesting) # defaults to 100
232
261
  @max_nesting = 100
@@ -243,7 +272,7 @@ module JSON
243
272
  # passed to the configure method.
244
273
  def to_h
245
274
  result = {}
246
- for iv in instance_variables
275
+ instance_variables.each do |iv|
247
276
  iv = iv.to_s[1..-1]
248
277
  result[iv.to_sym] = self[iv]
249
278
  end
@@ -287,7 +316,13 @@ module JSON
287
316
  # Converts this object to a string (calling #to_s), converts
288
317
  # it to a JSON string, and returns the result. This is a fallback, if no
289
318
  # special method #to_json was defined for some object.
290
- def to_json(*) to_s.to_json end
319
+ def to_json(generator_state)
320
+ if generator_state.strict?
321
+ raise GeneratorError, "#{self.class} not allowed in JSON"
322
+ else
323
+ to_s.to_json
324
+ end
325
+ end
291
326
  end
292
327
 
293
328
  module Hash
@@ -310,21 +345,18 @@ module JSON
310
345
  end
311
346
 
312
347
  def json_transform(state)
313
- delim = ','
314
- delim << state.object_nl
315
- result = '{'
316
- result << state.object_nl
348
+ delim = ",#{state.object_nl}"
349
+ result = "{#{state.object_nl}"
317
350
  depth = state.depth += 1
318
351
  first = true
319
352
  indent = !state.object_nl.empty?
320
- each { |key,value|
353
+ each { |key, value|
321
354
  result << delim unless first
322
355
  result << state.indent * depth if indent
323
- result << key.to_s.to_json(state)
324
- result << state.space_before
325
- result << ':'
326
- result << state.space
327
- if value.respond_to?(:to_json)
356
+ result = "#{result}#{key.to_s.to_json(state)}#{state.space_before}:#{state.space}"
357
+ if state.strict?
358
+ raise GeneratorError, "#{value.class} not allowed in JSON"
359
+ elsif value.respond_to?(:to_json)
328
360
  result << value.to_json(state)
329
361
  else
330
362
  result << %{"#{String(value)}"}
@@ -365,7 +397,9 @@ module JSON
365
397
  each { |value|
366
398
  result << delim unless first
367
399
  result << state.indent * depth if indent
368
- if value.respond_to?(:to_json)
400
+ if state.strict?
401
+ raise GeneratorError, "#{value.class} not allowed in JSON"
402
+ elsif value.respond_to?(:to_json)
369
403
  result << value.to_json(state)
370
404
  else
371
405
  result << %{"#{String(value)}"}
@@ -419,9 +453,9 @@ module JSON
419
453
  string = encode(::Encoding::UTF_8)
420
454
  end
421
455
  if state.ascii_only?
422
- '"' << JSON.utf8_to_json_ascii(string, state.escape_slash) << '"'
456
+ '"' << JSON.utf8_to_json_ascii(string, state.script_safe) << '"'
423
457
  else
424
- '"' << JSON.utf8_to_json(string, state.escape_slash) << '"'
458
+ '"' << JSON.utf8_to_json(string, state.script_safe) << '"'
425
459
  end
426
460
  end
427
461
 
data/lib/json/version.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: false
2
2
  module JSON
3
3
  # JSON version
4
- VERSION = '2.6.3'
4
+ VERSION = '2.7.2'
5
5
  VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc:
6
6
  VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
7
7
  VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
data/lib/json.rb CHANGED
@@ -285,6 +285,15 @@ require 'json/common'
285
285
  # # Raises JSON::NestingError (nesting of 2 is too deep):
286
286
  # JSON.generate(obj, max_nesting: 2)
287
287
  #
288
+ # ====== Escaping Options
289
+ #
290
+ # Options +script_safe+ (boolean) specifies wether <tt>'\u2028'</tt>, <tt>'\u2029'</tt>
291
+ # and <tt>'/'</tt> should be escaped as to make the JSON object safe to interpolate in script
292
+ # tags.
293
+ #
294
+ # Options +ascii_only+ (boolean) specifies wether all characters outside the ASCII range
295
+ # should be escaped.
296
+ #
288
297
  # ====== Output Options
289
298
  #
290
299
  # The default formatting options generate the most compact