json 2.10.2 → 2.15.1

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.
@@ -8,20 +8,8 @@ module JSON
8
8
  #
9
9
  # Instantiates a new State object, configured by _opts_.
10
10
  #
11
- # _opts_ can have the following keys:
12
- #
13
- # * *indent*: a string used to indent levels (default: ''),
14
- # * *space*: a string that is put after, a : or , delimiter (default: ''),
15
- # * *space_before*: a string that is put before a : pair delimiter (default: ''),
16
- # * *object_nl*: a string that is put at the end of a JSON object (default: ''),
17
- # * *array_nl*: a string that is put at the end of a JSON array (default: ''),
18
- # * *allow_nan*: true if NaN, Infinity, and -Infinity should be
19
- # generated, otherwise an exception is thrown, if these values are
20
- # encountered. This options defaults to false.
21
- # * *ascii_only*: true if only ASCII characters should be generated. This
22
- # option defaults to false.
23
- # * *buffer_initial_length*: sets the initial length of the generator's
24
- # internal buffer.
11
+ # Argument +opts+, if given, contains a \Hash of options for the generation.
12
+ # See {Generating Options}[#module-JSON-label-Generating+Options].
25
13
  def initialize(opts = nil)
26
14
  if opts && !opts.empty?
27
15
  configure(opts)
@@ -68,6 +56,11 @@ module JSON
68
56
  buffer_initial_length: buffer_initial_length,
69
57
  }
70
58
 
59
+ allow_duplicate_key = allow_duplicate_key?
60
+ unless allow_duplicate_key.nil?
61
+ result[:allow_duplicate_key] = allow_duplicate_key
62
+ end
63
+
71
64
  instance_variables.each do |iv|
72
65
  iv = iv.to_s[1..-1]
73
66
  result[iv.to_sym] = self[iv]
data/lib/json/ext.rb CHANGED
@@ -34,12 +34,12 @@ module JSON
34
34
 
35
35
  if RUBY_ENGINE == 'truffleruby'
36
36
  require 'json/truffle_ruby/generator'
37
- JSON.generator = ::JSON::TruffleRuby::Generator
37
+ JSON.generator = JSON::TruffleRuby::Generator
38
38
  else
39
39
  require 'json/ext/generator'
40
40
  JSON.generator = Generator
41
41
  end
42
42
  end
43
43
 
44
- JSON_LOADED = true unless defined?(::JSON::JSON_LOADED)
44
+ JSON_LOADED = true unless defined?(JSON::JSON_LOADED)
45
45
  end
@@ -52,14 +52,6 @@ module JSON
52
52
  table
53
53
  end
54
54
 
55
- def [](name)
56
- __send__(name)
57
- end unless method_defined?(:[])
58
-
59
- def []=(name, value)
60
- __send__("#{name}=", value)
61
- end unless method_defined?(:[]=)
62
-
63
55
  def |(other)
64
56
  self.class[other.to_hash.merge(to_hash)]
65
57
  end
@@ -47,6 +47,14 @@ module JSON
47
47
 
48
48
  SCRIPT_SAFE_ESCAPE_PATTERN = /[\/"\\\x0-\x1f\u2028-\u2029]/
49
49
 
50
+ def self.native_type?(value) # :nodoc:
51
+ (false == value || true == value || nil == value || String === value || Array === value || Hash === value || Integer === value || Float === value || Fragment === value)
52
+ end
53
+
54
+ def self.native_key?(key) # :nodoc:
55
+ (Symbol === key || String === key)
56
+ end
57
+
50
58
  # Convert a UTF8 encoded Ruby string _string_ to a JSON string, encoded with
51
59
  # UTF16 big endian characters as \u????, and return it.
52
60
  def self.utf8_to_json(string, script_safe = false) # :nodoc:
@@ -117,7 +125,7 @@ module JSON
117
125
  return new(opts.to_h)
118
126
  end
119
127
  end
120
- SAFE_STATE_PROTOTYPE.dup
128
+ new
121
129
  end
122
130
 
123
131
  # Instantiates a new State object, configured by _opts_.
@@ -271,6 +279,12 @@ module JSON
271
279
  false
272
280
  end
273
281
 
282
+ if opts.key?(:allow_duplicate_key)
283
+ @allow_duplicate_key = !!opts[:allow_duplicate_key]
284
+ else
285
+ @allow_duplicate_key = nil # nil is deprecation
286
+ end
287
+
274
288
  @strict = !!opts[:strict] if opts.key?(:strict)
275
289
 
276
290
  if !opts.key?(:max_nesting) # defaults to 100
@@ -284,6 +298,10 @@ module JSON
284
298
  end
285
299
  alias merge configure
286
300
 
301
+ def allow_duplicate_key? # :nodoc:
302
+ @allow_duplicate_key
303
+ end
304
+
287
305
  # Returns the configuration instance variables as a hash, that can be
288
306
  # passed to the configure method.
289
307
  def to_h
@@ -292,6 +310,11 @@ module JSON
292
310
  iv = iv.to_s[1..-1]
293
311
  result[iv.to_sym] = self[iv]
294
312
  end
313
+
314
+ if result[:allow_duplicate_key].nil?
315
+ result.delete(:allow_duplicate_key)
316
+ end
317
+
295
318
  result
296
319
  end
297
320
 
@@ -330,8 +353,17 @@ module JSON
330
353
  when Hash
331
354
  buf << '{'
332
355
  first = true
356
+ key_type = nil
333
357
  obj.each_pair do |k,v|
334
- buf << ',' unless first
358
+ if first
359
+ key_type = k.class
360
+ else
361
+ if key_type && !@allow_duplicate_key && key_type != k.class
362
+ key_type = nil # stop checking
363
+ JSON.send(:on_mixed_keys_hash, obj, !@allow_duplicate_key.nil?)
364
+ end
365
+ buf << ','
366
+ end
335
367
 
336
368
  key_str = k.to_s
337
369
  if key_str.class == String
@@ -424,10 +456,10 @@ module JSON
424
456
  state = State.from_state(state) if state
425
457
  if state&.strict?
426
458
  value = self
427
- if state.strict? && !(false == value || true == value || nil == value || String === value || Array === value || Hash === value || Integer === value || Float === value || Fragment === value)
459
+ if state.strict? && !Generator.native_type?(value)
428
460
  if state.as_json
429
- value = state.as_json.call(value)
430
- unless false == value || true == value || nil == value || String === value || Array === value || Hash === value || Integer === value || Float === value || Fragment === value
461
+ value = state.as_json.call(value, false)
462
+ unless Generator.native_type?(value)
431
463
  raise GeneratorError.new("#{value.class} returned by #{state.as_json} not allowed in JSON", value)
432
464
  end
433
465
  value.to_json(state)
@@ -471,11 +503,30 @@ module JSON
471
503
  delim = ",#{state.object_nl}"
472
504
  result = +"{#{state.object_nl}"
473
505
  first = true
506
+ key_type = nil
474
507
  indent = !state.object_nl.empty?
475
508
  each { |key, value|
476
- result << delim unless first
509
+ if first
510
+ key_type = key.class
511
+ else
512
+ if key_type && !state.allow_duplicate_key? && key_type != key.class
513
+ key_type = nil # stop checking
514
+ JSON.send(:on_mixed_keys_hash, self, state.allow_duplicate_key? == false)
515
+ end
516
+ result << delim
517
+ end
477
518
  result << state.indent * depth if indent
478
519
 
520
+ if state.strict? && !Generator.native_key?(key)
521
+ if state.as_json
522
+ key = state.as_json.call(key, true)
523
+ end
524
+
525
+ unless Generator.native_key?(key)
526
+ raise GeneratorError.new("#{key.class} not allowed as object key in JSON", value)
527
+ end
528
+ end
529
+
479
530
  key_str = key.to_s
480
531
  if key_str.is_a?(String)
481
532
  key_json = key_str.to_json(state)
@@ -484,10 +535,10 @@ module JSON
484
535
  end
485
536
 
486
537
  result = +"#{result}#{key_json}#{state.space_before}:#{state.space}"
487
- if state.strict? && !(false == value || true == value || nil == value || String === value || Array === value || Hash === value || Integer === value || Float === value || Fragment === value)
538
+ if state.strict? && !Generator.native_type?(value)
488
539
  if state.as_json
489
- value = state.as_json.call(value)
490
- unless false == value || true == value || nil == value || String === value || Array === value || Hash === value || Integer === value || Float === value || Fragment === value
540
+ value = state.as_json.call(value, false)
541
+ unless Generator.native_type?(value)
491
542
  raise GeneratorError.new("#{value.class} returned by #{state.as_json} not allowed in JSON", value)
492
543
  end
493
544
  result << value.to_json(state)
@@ -545,10 +596,10 @@ module JSON
545
596
  each { |value|
546
597
  result << delim unless first
547
598
  result << state.indent * depth if indent
548
- if state.strict? && !(false == value || true == value || nil == value || String === value || Array === value || Hash === value || Integer === value || Float === value || Fragment === value || Symbol == value)
599
+ if state.strict? && !Generator.native_type?(value)
549
600
  if state.as_json
550
- value = state.as_json.call(value)
551
- unless false == value || true == value || nil == value || String === value || Array === value || Hash === value || Integer === value || Float === value || Fragment === value || Symbol === value
601
+ value = state.as_json.call(value, false)
602
+ unless Generator.native_type?(value)
552
603
  raise GeneratorError.new("#{value.class} returned by #{state.as_json} not allowed in JSON", value)
553
604
  end
554
605
  result << value.to_json(state)
@@ -582,7 +633,7 @@ module JSON
582
633
  if state.allow_nan?
583
634
  to_s
584
635
  elsif state.strict? && state.as_json
585
- casted_value = state.as_json.call(self)
636
+ casted_value = state.as_json.call(self, false)
586
637
 
587
638
  if casted_value.equal?(self)
588
639
  raise GeneratorError.new("#{self} not allowed in JSON", self)
@@ -635,39 +686,6 @@ module JSON
635
686
  rescue Encoding::UndefinedConversionError => error
636
687
  raise ::JSON::GeneratorError.new(error.message, self)
637
688
  end
638
-
639
- # Module that holds the extending methods if, the String module is
640
- # included.
641
- module Extend
642
- # Raw Strings are JSON Objects (the raw bytes are stored in an
643
- # array for the key "raw"). The Ruby String can be created by this
644
- # module method.
645
- def json_create(o)
646
- o['raw'].pack('C*')
647
- end
648
- end
649
-
650
- # Extends _modul_ with the String::Extend module.
651
- def self.included(modul)
652
- modul.extend Extend
653
- end
654
-
655
- # This method creates a raw object hash, that can be nested into
656
- # other data structures and will be unparsed as a raw string. This
657
- # method should be used, if you want to convert raw strings to JSON
658
- # instead of UTF-8 strings, e. g. binary data.
659
- def to_json_raw_object
660
- {
661
- JSON.create_id => self.class.name,
662
- 'raw' => self.unpack('C*'),
663
- }
664
- end
665
-
666
- # This method creates a JSON text from the result of
667
- # a call to to_json_raw_object of this String.
668
- def to_json_raw(*args)
669
- to_json_raw_object.to_json(*args)
670
- end
671
689
  end
672
690
 
673
691
  module TrueClass
data/lib/json/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JSON
4
- VERSION = '2.10.2'
4
+ VERSION = '2.15.1'
5
5
  end
data/lib/json.rb CHANGED
@@ -127,6 +127,24 @@ require 'json/common'
127
127
  #
128
128
  # ---
129
129
  #
130
+ # Option +allow_duplicate_key+ specifies whether duplicate keys in objects
131
+ # should be ignored or cause an error to be raised:
132
+ #
133
+ # When not specified:
134
+ # # The last value is used and a deprecation warning emitted.
135
+ # JSON.parse('{"a": 1, "a":2}') => {"a" => 2}
136
+ # # warning: detected duplicate keys in JSON object.
137
+ # # This will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`
138
+ #
139
+ # When set to `+true+`
140
+ # # The last value is used.
141
+ # JSON.parse('{"a": 1, "a":2}') => {"a" => 2}
142
+ #
143
+ # When set to `+false+`, the future default:
144
+ # JSON.parse('{"a": 1, "a":2}') => duplicate key at line 1 column 1 (JSON::ParserError)
145
+ #
146
+ # ---
147
+ #
130
148
  # Option +allow_nan+ (boolean) specifies whether to allow
131
149
  # NaN, Infinity, and MinusInfinity in +source+;
132
150
  # defaults to +false+.
@@ -143,8 +161,23 @@ require 'json/common'
143
161
  # ruby = JSON.parse(source, {allow_nan: true})
144
162
  # ruby # => [NaN, Infinity, -Infinity]
145
163
  #
164
+ # ---
165
+ #
166
+ # Option +allow_trailing_comma+ (boolean) specifies whether to allow
167
+ # trailing commas in objects and arrays;
168
+ # defaults to +false+.
169
+ #
170
+ # With the default, +false+:
171
+ # JSON.parse('[1,]') # unexpected character: ']' at line 1 column 4 (JSON::ParserError)
172
+ #
173
+ # When enabled:
174
+ # JSON.parse('[1,]', allow_trailing_comma: true) # => [1]
175
+ #
146
176
  # ====== Output Options
147
177
  #
178
+ # Option +freeze+ (boolean) specifies whether the returned objects will be frozen;
179
+ # defaults to +false+.
180
+ #
148
181
  # Option +symbolize_names+ (boolean) specifies whether returned \Hash keys
149
182
  # should be Symbols;
150
183
  # defaults to +false+ (use Strings).
@@ -274,6 +307,25 @@ require 'json/common'
274
307
  #
275
308
  # ---
276
309
  #
310
+ # Option +allow_duplicate_key+ (boolean) specifies whether
311
+ # hashes with duplicate keys should be allowed or produce an error.
312
+ # defaults to emit a deprecation warning.
313
+ #
314
+ # With the default, (not set):
315
+ # Warning[:deprecated] = true
316
+ # JSON.generate({ foo: 1, "foo" => 2 })
317
+ # # warning: detected duplicate key "foo" in {foo: 1, "foo" => 2}.
318
+ # # This will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`
319
+ # # => '{"foo":1,"foo":2}'
320
+ #
321
+ # With <tt>false</tt>
322
+ # JSON.generate({ foo: 1, "foo" => 2 }, allow_duplicate_key: false)
323
+ # # detected duplicate key "foo" in {foo: 1, "foo" => 2} (JSON::GeneratorError)
324
+ #
325
+ # In version 3.0, <tt>false</tt> will become the default.
326
+ #
327
+ # ---
328
+ #
277
329
  # Option +max_nesting+ (\Integer) specifies the maximum nesting depth
278
330
  # in +obj+; defaults to +100+.
279
331
  #
@@ -351,6 +403,9 @@ require 'json/common'
351
403
  #
352
404
  # == \JSON Additions
353
405
  #
406
+ # Note that JSON Additions must only be used with trusted data, and is
407
+ # deprecated.
408
+ #
354
409
  # When you "round trip" a non-\String object from Ruby to \JSON and back,
355
410
  # you have a new \String, instead of the object you began with:
356
411
  # ruby0 = Range.new(0, 2)
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.10.2
4
+ version: 2.15.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Frank
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-03-12 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies: []
12
12
  description: This is a JSON implementation as a Ruby extension in C.
13
13
  email: flori@ping.de
@@ -28,6 +28,10 @@ files:
28
28
  - ext/json/ext/generator/generator.c
29
29
  - ext/json/ext/parser/extconf.rb
30
30
  - ext/json/ext/parser/parser.c
31
+ - ext/json/ext/simd/conf.rb
32
+ - ext/json/ext/simd/simd.h
33
+ - ext/json/ext/vendor/fpconv.c
34
+ - ext/json/ext/vendor/jeaiii-ltoa.h
31
35
  - json.gemspec
32
36
  - lib/json.rb
33
37
  - lib/json/add/bigdecimal.rb
@@ -41,6 +45,7 @@ files:
41
45
  - lib/json/add/rational.rb
42
46
  - lib/json/add/regexp.rb
43
47
  - lib/json/add/set.rb
48
+ - lib/json/add/string.rb
44
49
  - lib/json/add/struct.rb
45
50
  - lib/json/add/symbol.rb
46
51
  - lib/json/add/time.rb
@@ -77,7 +82,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
77
82
  - !ruby/object:Gem::Version
78
83
  version: '0'
79
84
  requirements: []
80
- rubygems_version: 3.6.2
85
+ rubygems_version: 3.6.9
81
86
  specification_version: 4
82
87
  summary: JSON Implementation for Ruby
83
88
  test_files: []