json 2.13.1 → 2.19.2
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.
- checksums.yaml +4 -4
- data/CHANGES.md +98 -8
- data/LEGAL +12 -0
- data/README.md +19 -1
- data/ext/json/ext/fbuffer/fbuffer.h +47 -66
- data/ext/json/ext/generator/extconf.rb +1 -1
- data/ext/json/ext/generator/generator.c +375 -552
- data/ext/json/ext/json.h +105 -0
- data/ext/json/ext/parser/extconf.rb +2 -1
- data/ext/json/ext/parser/parser.c +661 -473
- data/ext/json/ext/simd/simd.h +81 -60
- data/ext/json/ext/vendor/fpconv.c +13 -12
- data/ext/json/ext/vendor/ryu.h +819 -0
- data/lib/json/add/core.rb +1 -0
- data/lib/json/add/string.rb +35 -0
- data/lib/json/common.rb +118 -49
- data/lib/json/ext/generator/state.rb +11 -14
- data/lib/json/generic_object.rb +0 -8
- data/lib/json/truffle_ruby/generator.rb +126 -64
- data/lib/json/version.rb +1 -1
- data/lib/json.rb +56 -1
- metadata +6 -3
data/lib/json/add/core.rb
CHANGED
|
@@ -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
|
@@ -48,7 +48,7 @@ module JSON
|
|
|
48
48
|
end
|
|
49
49
|
end
|
|
50
50
|
|
|
51
|
-
# TODO:
|
|
51
|
+
# TODO: extract :create_additions support to another gem for version 3.0
|
|
52
52
|
def create_additions_proc(opts)
|
|
53
53
|
if opts[:symbolize_names]
|
|
54
54
|
raise ArgumentError, "options :symbolize_names and :create_additions cannot be used in conjunction"
|
|
@@ -71,9 +71,14 @@ module JSON
|
|
|
71
71
|
end
|
|
72
72
|
when object_class
|
|
73
73
|
if opts[:create_additions] != false
|
|
74
|
-
if
|
|
75
|
-
klass =
|
|
76
|
-
|
|
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
|
|
@@ -87,31 +92,32 @@ module JSON
|
|
|
87
92
|
opts
|
|
88
93
|
end
|
|
89
94
|
|
|
90
|
-
GEM_ROOT = File.expand_path("../../../", __FILE__) + "/"
|
|
91
95
|
def create_additions_warning
|
|
92
|
-
|
|
96
|
+
JSON.deprecation_warning "JSON.load implicit support for `create_additions: true` is deprecated " \
|
|
93
97
|
"and will be removed in 3.0, use JSON.unsafe_load or explicitly " \
|
|
94
98
|
"pass `create_additions: true`"
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
95
102
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
if RUBY_VERSION >= "3.0"
|
|
106
|
-
warn(message, uplevel: uplevel - 1, category: :deprecated)
|
|
103
|
+
class << self
|
|
104
|
+
def deprecation_warning(message, uplevel = 3) # :nodoc:
|
|
105
|
+
gem_root = File.expand_path("..", __dir__) + "/"
|
|
106
|
+
caller_locations(uplevel, 10).each do |frame|
|
|
107
|
+
if frame.path.nil? || frame.path.start_with?(gem_root) || frame.path.end_with?("/truffle/cext_ruby.rb", ".c")
|
|
108
|
+
uplevel += 1
|
|
107
109
|
else
|
|
108
|
-
|
|
110
|
+
break
|
|
109
111
|
end
|
|
110
112
|
end
|
|
113
|
+
|
|
114
|
+
if RUBY_VERSION >= "3.0"
|
|
115
|
+
warn(message, uplevel: uplevel, category: :deprecated)
|
|
116
|
+
else
|
|
117
|
+
warn(message, uplevel: uplevel)
|
|
118
|
+
end
|
|
111
119
|
end
|
|
112
|
-
end
|
|
113
120
|
|
|
114
|
-
class << self
|
|
115
121
|
# :call-seq:
|
|
116
122
|
# JSON[object] -> new_array or new_string
|
|
117
123
|
#
|
|
@@ -146,29 +152,21 @@ module JSON
|
|
|
146
152
|
const_set :Parser, parser
|
|
147
153
|
end
|
|
148
154
|
|
|
149
|
-
# Return the constant located at _path_. The format of _path_ has to be
|
|
150
|
-
# either ::A::B::C or A::B::C. In any case, A has to be located at the top
|
|
151
|
-
# level (absolute namespace path?). If there doesn't exist a constant at
|
|
152
|
-
# the given path, an ArgumentError is raised.
|
|
153
|
-
def deep_const_get(path) # :nodoc:
|
|
154
|
-
Object.const_get(path)
|
|
155
|
-
rescue NameError => e
|
|
156
|
-
raise ArgumentError, "can't get const #{path}: #{e}"
|
|
157
|
-
end
|
|
158
|
-
|
|
159
155
|
# Set the module _generator_ to be used by JSON.
|
|
160
156
|
def generator=(generator) # :nodoc:
|
|
161
157
|
old, $VERBOSE = $VERBOSE, nil
|
|
162
158
|
@generator = generator
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
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
|
|
170
169
|
end
|
|
171
|
-
include modul
|
|
172
170
|
end
|
|
173
171
|
end
|
|
174
172
|
self.state = generator::State
|
|
@@ -185,6 +183,25 @@ module JSON
|
|
|
185
183
|
|
|
186
184
|
private
|
|
187
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
|
+
|
|
188
205
|
def deprecated_singleton_attr_accessor(*attrs)
|
|
189
206
|
args = RUBY_VERSION >= "3.0" ? ", category: :deprecated" : ""
|
|
190
207
|
attrs.each do |attr|
|
|
@@ -390,7 +407,7 @@ module JSON
|
|
|
390
407
|
#
|
|
391
408
|
# Returns a \String containing the generated \JSON data.
|
|
392
409
|
#
|
|
393
|
-
# See also JSON.
|
|
410
|
+
# See also JSON.pretty_generate.
|
|
394
411
|
#
|
|
395
412
|
# Argument +obj+ is the Ruby object to be converted to \JSON.
|
|
396
413
|
#
|
|
@@ -535,6 +552,7 @@ module JSON
|
|
|
535
552
|
:create_additions => nil,
|
|
536
553
|
}
|
|
537
554
|
# :call-seq:
|
|
555
|
+
# JSON.unsafe_load(source, options = {}) -> object
|
|
538
556
|
# JSON.unsafe_load(source, proc = nil, options = {}) -> object
|
|
539
557
|
#
|
|
540
558
|
# Returns the Ruby objects created by parsing the given +source+.
|
|
@@ -642,6 +660,7 @@ module JSON
|
|
|
642
660
|
# when Array
|
|
643
661
|
# obj.map! {|v| deserialize_obj v }
|
|
644
662
|
# end
|
|
663
|
+
# obj
|
|
645
664
|
# })
|
|
646
665
|
# pp ruby
|
|
647
666
|
# Output:
|
|
@@ -665,7 +684,12 @@ module JSON
|
|
|
665
684
|
#
|
|
666
685
|
def unsafe_load(source, proc = nil, options = nil)
|
|
667
686
|
opts = if options.nil?
|
|
668
|
-
|
|
687
|
+
if proc && proc.is_a?(Hash)
|
|
688
|
+
options, proc = proc, nil
|
|
689
|
+
options
|
|
690
|
+
else
|
|
691
|
+
_unsafe_load_default_options
|
|
692
|
+
end
|
|
669
693
|
else
|
|
670
694
|
_unsafe_load_default_options.merge(options)
|
|
671
695
|
end
|
|
@@ -683,12 +707,17 @@ module JSON
|
|
|
683
707
|
if opts[:allow_blank] && (source.nil? || source.empty?)
|
|
684
708
|
source = 'null'
|
|
685
709
|
end
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
710
|
+
|
|
711
|
+
if proc
|
|
712
|
+
opts = opts.dup
|
|
713
|
+
opts[:on_load] = proc.to_proc
|
|
714
|
+
end
|
|
715
|
+
|
|
716
|
+
parse(source, opts)
|
|
689
717
|
end
|
|
690
718
|
|
|
691
719
|
# :call-seq:
|
|
720
|
+
# JSON.load(source, options = {}) -> object
|
|
692
721
|
# JSON.load(source, proc = nil, options = {}) -> object
|
|
693
722
|
#
|
|
694
723
|
# Returns the Ruby objects created by parsing the given +source+.
|
|
@@ -802,6 +831,7 @@ module JSON
|
|
|
802
831
|
# when Array
|
|
803
832
|
# obj.map! {|v| deserialize_obj v }
|
|
804
833
|
# end
|
|
834
|
+
# obj
|
|
805
835
|
# })
|
|
806
836
|
# pp ruby
|
|
807
837
|
# Output:
|
|
@@ -824,8 +854,18 @@ module JSON
|
|
|
824
854
|
# @attributes={"type"=>"Admin", "password"=>"0wn3d"}>}
|
|
825
855
|
#
|
|
826
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
|
+
|
|
827
862
|
opts = if options.nil?
|
|
828
|
-
|
|
863
|
+
if proc && proc.is_a?(Hash)
|
|
864
|
+
options, proc = proc, nil
|
|
865
|
+
options
|
|
866
|
+
else
|
|
867
|
+
_load_default_options
|
|
868
|
+
end
|
|
829
869
|
else
|
|
830
870
|
_load_default_options.merge(options)
|
|
831
871
|
end
|
|
@@ -840,7 +880,7 @@ module JSON
|
|
|
840
880
|
end
|
|
841
881
|
end
|
|
842
882
|
|
|
843
|
-
if opts[:allow_blank] && (source.nil? || source.empty?)
|
|
883
|
+
if opts[:allow_blank] && (source.nil? || (String === source && source.empty?))
|
|
844
884
|
source = 'null'
|
|
845
885
|
end
|
|
846
886
|
|
|
@@ -998,10 +1038,11 @@ module JSON
|
|
|
998
1038
|
# JSON.new(options = nil, &block)
|
|
999
1039
|
#
|
|
1000
1040
|
# Argument +options+, if given, contains a \Hash of options for both parsing and generating.
|
|
1001
|
-
# See {Parsing Options}[
|
|
1041
|
+
# See {Parsing Options}[rdoc-ref:JSON@Parsing+Options],
|
|
1042
|
+
# and {Generating Options}[rdoc-ref:JSON@Generating+Options].
|
|
1002
1043
|
#
|
|
1003
1044
|
# For generation, the <tt>strict: true</tt> option is always set. When a Ruby object with no native \JSON counterpart is
|
|
1004
|
-
#
|
|
1045
|
+
# encountered, the block provided to the initialize method is invoked, and must return a Ruby object that has a native
|
|
1005
1046
|
# \JSON counterpart:
|
|
1006
1047
|
#
|
|
1007
1048
|
# module MyApp
|
|
@@ -1027,7 +1068,7 @@ module JSON
|
|
|
1027
1068
|
options[:as_json] = as_json if as_json
|
|
1028
1069
|
|
|
1029
1070
|
@state = State.new(options).freeze
|
|
1030
|
-
@parser_config = Ext::Parser::Config.new(ParserOptions.prepare(options))
|
|
1071
|
+
@parser_config = Ext::Parser::Config.new(ParserOptions.prepare(options)).freeze
|
|
1031
1072
|
end
|
|
1032
1073
|
|
|
1033
1074
|
# call-seq:
|
|
@@ -1036,7 +1077,7 @@ module JSON
|
|
|
1036
1077
|
#
|
|
1037
1078
|
# Serialize the given object into a \JSON document.
|
|
1038
1079
|
def dump(object, io = nil)
|
|
1039
|
-
@state.
|
|
1080
|
+
@state.generate(object, io)
|
|
1040
1081
|
end
|
|
1041
1082
|
alias_method :generate, :dump
|
|
1042
1083
|
|
|
@@ -1057,6 +1098,30 @@ module JSON
|
|
|
1057
1098
|
load(File.read(path, encoding: Encoding::UTF_8))
|
|
1058
1099
|
end
|
|
1059
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
|
|
1060
1125
|
end
|
|
1061
1126
|
|
|
1062
1127
|
module ::Kernel
|
|
@@ -1102,3 +1167,7 @@ module ::Kernel
|
|
|
1102
1167
|
JSON[object, opts]
|
|
1103
1168
|
end
|
|
1104
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
|
-
#
|
|
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
|
data/lib/json/generic_object.rb
CHANGED
|
@@ -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
|