json 2.13.2 → 2.19.3

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.
data/lib/json/add/core.rb CHANGED
@@ -7,6 +7,7 @@ require 'json/add/date_time'
7
7
  require 'json/add/exception'
8
8
  require 'json/add/range'
9
9
  require 'json/add/regexp'
10
+ require 'json/add/string'
10
11
  require 'json/add/struct'
11
12
  require 'json/add/symbol'
12
13
  require 'json/add/time'
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
3
+ require 'json'
4
+ end
5
+
6
+ class String
7
+ # call-seq: json_create(o)
8
+ #
9
+ # Raw Strings are JSON Objects (the raw bytes are stored in an array for the
10
+ # key "raw"). The Ruby String can be created by this class method.
11
+ def self.json_create(object)
12
+ object["raw"].pack("C*")
13
+ end
14
+
15
+ # call-seq: to_json_raw_object()
16
+ #
17
+ # This method creates a raw object hash, that can be nested into
18
+ # other data structures and will be generated as a raw string. This
19
+ # method should be used, if you want to convert raw strings to JSON
20
+ # instead of UTF-8 strings, e. g. binary data.
21
+ def to_json_raw_object
22
+ {
23
+ JSON.create_id => self.class.name,
24
+ "raw" => unpack("C*"),
25
+ }
26
+ end
27
+
28
+ # call-seq: to_json_raw(*args)
29
+ #
30
+ # This method creates a JSON text from the result of a call to
31
+ # to_json_raw_object of this String.
32
+ def to_json_raw(...)
33
+ to_json_raw_object.to_json(...)
34
+ end
35
+ end
data/lib/json/common.rb CHANGED
@@ -71,9 +71,14 @@ module JSON
71
71
  end
72
72
  when object_class
73
73
  if opts[:create_additions] != false
74
- if class_name = object[JSON.create_id]
75
- klass = JSON.deep_const_get(class_name)
76
- if (klass.respond_to?(:json_creatable?) && klass.json_creatable?) || klass.respond_to?(:json_create)
74
+ if class_path = object[JSON.create_id]
75
+ klass = begin
76
+ Object.const_get(class_path)
77
+ rescue NameError => e
78
+ raise ArgumentError, "can't get const #{class_path}: #{e}"
79
+ end
80
+
81
+ if klass.respond_to?(:json_creatable?) ? klass.json_creatable? : klass.respond_to?(:json_create)
77
82
  create_additions_warning if create_additions.nil?
78
83
  object = klass.json_create(object)
79
84
  end
@@ -97,7 +102,7 @@ module JSON
97
102
 
98
103
  class << self
99
104
  def deprecation_warning(message, uplevel = 3) # :nodoc:
100
- gem_root = File.expand_path("../../../", __FILE__) + "/"
105
+ gem_root = File.expand_path("..", __dir__) + "/"
101
106
  caller_locations(uplevel, 10).each do |frame|
102
107
  if frame.path.nil? || frame.path.start_with?(gem_root) || frame.path.end_with?("/truffle/cext_ruby.rb", ".c")
103
108
  uplevel += 1
@@ -147,29 +152,21 @@ module JSON
147
152
  const_set :Parser, parser
148
153
  end
149
154
 
150
- # Return the constant located at _path_. The format of _path_ has to be
151
- # either ::A::B::C or A::B::C. In any case, A has to be located at the top
152
- # level (absolute namespace path?). If there doesn't exist a constant at
153
- # the given path, an ArgumentError is raised.
154
- def deep_const_get(path) # :nodoc:
155
- Object.const_get(path)
156
- rescue NameError => e
157
- raise ArgumentError, "can't get const #{path}: #{e}"
158
- end
159
-
160
155
  # Set the module _generator_ to be used by JSON.
161
156
  def generator=(generator) # :nodoc:
162
157
  old, $VERBOSE = $VERBOSE, nil
163
158
  @generator = generator
164
- generator_methods = generator::GeneratorMethods
165
- for const in generator_methods.constants
166
- klass = const_get(const)
167
- modul = generator_methods.const_get(const)
168
- klass.class_eval do
169
- instance_methods(false).each do |m|
170
- m.to_s == 'to_json' and remove_method m
159
+ if generator.const_defined?(:GeneratorMethods)
160
+ generator_methods = generator::GeneratorMethods
161
+ for const in generator_methods.constants
162
+ klass = const_get(const)
163
+ modul = generator_methods.const_get(const)
164
+ klass.class_eval do
165
+ instance_methods(false).each do |m|
166
+ m.to_s == 'to_json' and remove_method m
167
+ end
168
+ include modul
171
169
  end
172
- include modul
173
170
  end
174
171
  end
175
172
  self.state = generator::State
@@ -186,6 +183,25 @@ module JSON
186
183
 
187
184
  private
188
185
 
186
+ # Called from the extension when a hash has both string and symbol keys
187
+ def on_mixed_keys_hash(hash, do_raise)
188
+ set = {}
189
+ hash.each_key do |key|
190
+ key_str = key.to_s
191
+
192
+ if set[key_str]
193
+ message = "detected duplicate key #{key_str.inspect} in #{hash.inspect}"
194
+ if do_raise
195
+ raise GeneratorError, message
196
+ else
197
+ deprecation_warning("#{message}.\nThis will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`")
198
+ end
199
+ else
200
+ set[key_str] = true
201
+ end
202
+ end
203
+ end
204
+
189
205
  def deprecated_singleton_attr_accessor(*attrs)
190
206
  args = RUBY_VERSION >= "3.0" ? ", category: :deprecated" : ""
191
207
  attrs.each do |attr|
@@ -391,7 +407,7 @@ module JSON
391
407
  #
392
408
  # Returns a \String containing the generated \JSON data.
393
409
  #
394
- # See also JSON.fast_generate, JSON.pretty_generate.
410
+ # See also JSON.pretty_generate.
395
411
  #
396
412
  # Argument +obj+ is the Ruby object to be converted to \JSON.
397
413
  #
@@ -536,6 +552,7 @@ module JSON
536
552
  :create_additions => nil,
537
553
  }
538
554
  # :call-seq:
555
+ # JSON.unsafe_load(source, options = {}) -> object
539
556
  # JSON.unsafe_load(source, proc = nil, options = {}) -> object
540
557
  #
541
558
  # Returns the Ruby objects created by parsing the given +source+.
@@ -643,6 +660,7 @@ module JSON
643
660
  # when Array
644
661
  # obj.map! {|v| deserialize_obj v }
645
662
  # end
663
+ # obj
646
664
  # })
647
665
  # pp ruby
648
666
  # Output:
@@ -666,7 +684,12 @@ module JSON
666
684
  #
667
685
  def unsafe_load(source, proc = nil, options = nil)
668
686
  opts = if options.nil?
669
- _unsafe_load_default_options
687
+ if proc && proc.is_a?(Hash)
688
+ options, proc = proc, nil
689
+ options
690
+ else
691
+ _unsafe_load_default_options
692
+ end
670
693
  else
671
694
  _unsafe_load_default_options.merge(options)
672
695
  end
@@ -684,12 +707,17 @@ module JSON
684
707
  if opts[:allow_blank] && (source.nil? || source.empty?)
685
708
  source = 'null'
686
709
  end
687
- result = parse(source, opts)
688
- recurse_proc(result, &proc) if proc
689
- result
710
+
711
+ if proc
712
+ opts = opts.dup
713
+ opts[:on_load] = proc.to_proc
714
+ end
715
+
716
+ parse(source, opts)
690
717
  end
691
718
 
692
719
  # :call-seq:
720
+ # JSON.load(source, options = {}) -> object
693
721
  # JSON.load(source, proc = nil, options = {}) -> object
694
722
  #
695
723
  # Returns the Ruby objects created by parsing the given +source+.
@@ -803,6 +831,7 @@ module JSON
803
831
  # when Array
804
832
  # obj.map! {|v| deserialize_obj v }
805
833
  # end
834
+ # obj
806
835
  # })
807
836
  # pp ruby
808
837
  # Output:
@@ -825,8 +854,18 @@ module JSON
825
854
  # @attributes={"type"=>"Admin", "password"=>"0wn3d"}>}
826
855
  #
827
856
  def load(source, proc = nil, options = nil)
857
+ if proc && options.nil? && proc.is_a?(Hash)
858
+ options = proc
859
+ proc = nil
860
+ end
861
+
828
862
  opts = if options.nil?
829
- _load_default_options
863
+ if proc && proc.is_a?(Hash)
864
+ options, proc = proc, nil
865
+ options
866
+ else
867
+ _load_default_options
868
+ end
830
869
  else
831
870
  _load_default_options.merge(options)
832
871
  end
@@ -841,7 +880,7 @@ module JSON
841
880
  end
842
881
  end
843
882
 
844
- if opts[:allow_blank] && (source.nil? || source.empty?)
883
+ if opts[:allow_blank] && (source.nil? || (String === source && source.empty?))
845
884
  source = 'null'
846
885
  end
847
886
 
@@ -999,10 +1038,11 @@ module JSON
999
1038
  # JSON.new(options = nil, &block)
1000
1039
  #
1001
1040
  # Argument +options+, if given, contains a \Hash of options for both parsing and generating.
1002
- # See {Parsing Options}[#module-JSON-label-Parsing+Options], and {Generating Options}[#module-JSON-label-Generating+Options].
1041
+ # See {Parsing Options}[rdoc-ref:JSON@Parsing+Options],
1042
+ # and {Generating Options}[rdoc-ref:JSON@Generating+Options].
1003
1043
  #
1004
1044
  # For generation, the <tt>strict: true</tt> option is always set. When a Ruby object with no native \JSON counterpart is
1005
- # encoutered, the block provided to the initialize method is invoked, and must return a Ruby object that has a native
1045
+ # encountered, the block provided to the initialize method is invoked, and must return a Ruby object that has a native
1006
1046
  # \JSON counterpart:
1007
1047
  #
1008
1048
  # module MyApp
@@ -1028,7 +1068,7 @@ module JSON
1028
1068
  options[:as_json] = as_json if as_json
1029
1069
 
1030
1070
  @state = State.new(options).freeze
1031
- @parser_config = Ext::Parser::Config.new(ParserOptions.prepare(options))
1071
+ @parser_config = Ext::Parser::Config.new(ParserOptions.prepare(options)).freeze
1032
1072
  end
1033
1073
 
1034
1074
  # call-seq:
@@ -1037,7 +1077,7 @@ module JSON
1037
1077
  #
1038
1078
  # Serialize the given object into a \JSON document.
1039
1079
  def dump(object, io = nil)
1040
- @state.generate_new(object, io)
1080
+ @state.generate(object, io)
1041
1081
  end
1042
1082
  alias_method :generate, :dump
1043
1083
 
@@ -1058,6 +1098,30 @@ module JSON
1058
1098
  load(File.read(path, encoding: Encoding::UTF_8))
1059
1099
  end
1060
1100
  end
1101
+
1102
+ module GeneratorMethods
1103
+ # call-seq: to_json(*)
1104
+ #
1105
+ # Converts this object into a JSON string.
1106
+ # If this object doesn't directly maps to a JSON native type,
1107
+ # first convert it to a string (calling #to_s), then converts
1108
+ # it to a JSON string, and returns the result.
1109
+ # This is a fallback, if no special method #to_json was defined for some object.
1110
+ def to_json(state = nil, *)
1111
+ obj = case self
1112
+ when nil, false, true, Integer, Float, Array, Hash
1113
+ self
1114
+ else
1115
+ "#{self}"
1116
+ end
1117
+
1118
+ if state.nil?
1119
+ JSON::State._generate_no_fallback(obj, nil, nil)
1120
+ else
1121
+ JSON::State.from_state(state)._generate_no_fallback(obj)
1122
+ end
1123
+ end
1124
+ end
1061
1125
  end
1062
1126
 
1063
1127
  module ::Kernel
@@ -1103,3 +1167,7 @@ module ::Kernel
1103
1167
  JSON[object, opts]
1104
1168
  end
1105
1169
  end
1170
+
1171
+ class Object
1172
+ include JSON::GeneratorMethods
1173
+ end
@@ -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}[rdoc-ref:JSON@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]
@@ -82,6 +75,8 @@ module JSON
82
75
  #
83
76
  # Returns the value returned by method +name+.
84
77
  def [](name)
78
+ ::JSON.deprecation_warning("JSON::State#[] is deprecated and will be removed in json 3.0.0")
79
+
85
80
  if respond_to?(name)
86
81
  __send__(name)
87
82
  else
@@ -94,6 +89,8 @@ module JSON
94
89
  #
95
90
  # Sets the attribute name to value.
96
91
  def []=(name, value)
92
+ ::JSON.deprecation_warning("JSON::State#[]= is deprecated and will be removed in json 3.0.0")
93
+
97
94
  if respond_to?(name_writer = "#{name}=")
98
95
  __send__ name_writer, value
99
96
  else
@@ -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