json 2.16.0 → 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.
- checksums.yaml +4 -4
- data/CHANGES.md +43 -1
- data/ext/json/ext/fbuffer/fbuffer.h +29 -25
- data/ext/json/ext/generator/extconf.rb +1 -1
- data/ext/json/ext/generator/generator.c +132 -369
- data/ext/json/ext/json.h +13 -0
- data/ext/json/ext/parser/extconf.rb +1 -2
- data/ext/json/ext/parser/parser.c +235 -179
- data/ext/json/ext/simd/simd.h +33 -16
- data/ext/json/ext/vendor/fpconv.c +3 -3
- data/lib/json/common.rb +62 -14
- data/lib/json/ext/generator/state.rb +1 -1
- data/lib/json/truffle_ruby/generator.rb +34 -18
- data/lib/json/version.rb +1 -1
- data/lib/json.rb +33 -0
- metadata +2 -2
data/ext/json/ext/simd/simd.h
CHANGED
|
@@ -58,7 +58,34 @@ static inline int trailing_zeros(int input)
|
|
|
58
58
|
|
|
59
59
|
#ifdef JSON_ENABLE_SIMD
|
|
60
60
|
|
|
61
|
-
#define SIMD_MINIMUM_THRESHOLD
|
|
61
|
+
#define SIMD_MINIMUM_THRESHOLD 4
|
|
62
|
+
|
|
63
|
+
ALWAYS_INLINE(static) void json_fast_memcpy16(char *dst, const char *src, size_t len)
|
|
64
|
+
{
|
|
65
|
+
RBIMPL_ASSERT_OR_ASSUME(len < 16);
|
|
66
|
+
RBIMPL_ASSERT_OR_ASSUME(len >= SIMD_MINIMUM_THRESHOLD); // 4
|
|
67
|
+
#if defined(__has_builtin) && __has_builtin(__builtin_memcpy)
|
|
68
|
+
// If __builtin_memcpy is available, use it to copy between SIMD_MINIMUM_THRESHOLD (4) and vec_len-1 (15) bytes.
|
|
69
|
+
// These copies overlap. The first copy will copy the first 8 (or 4) bytes. The second copy will copy
|
|
70
|
+
// the last 8 (or 4) bytes but overlap with the first copy. The overlapping bytes will be in the correct
|
|
71
|
+
// position in both copies.
|
|
72
|
+
|
|
73
|
+
// Please do not attempt to replace __builtin_memcpy with memcpy without profiling and/or looking at the
|
|
74
|
+
// generated assembly. On clang-specifically (tested on Apple clang version 17.0.0 (clang-1700.0.13.3)),
|
|
75
|
+
// when using memcpy, the compiler will notice the only difference is a 4 or 8 and generate a conditional
|
|
76
|
+
// select instruction instead of direct loads and stores with a branch. This ends up slower than the branch
|
|
77
|
+
// plus two loads and stores generated when using __builtin_memcpy.
|
|
78
|
+
if (len >= 8) {
|
|
79
|
+
__builtin_memcpy(dst, src, 8);
|
|
80
|
+
__builtin_memcpy(dst + len - 8, src + len - 8, 8);
|
|
81
|
+
} else {
|
|
82
|
+
__builtin_memcpy(dst, src, 4);
|
|
83
|
+
__builtin_memcpy(dst + len - 4, src + len - 4, 4);
|
|
84
|
+
}
|
|
85
|
+
#else
|
|
86
|
+
MEMCPY(dst, src, char, len);
|
|
87
|
+
#endif
|
|
88
|
+
}
|
|
62
89
|
|
|
63
90
|
#if defined(__ARM_NEON) || defined(__ARM_NEON__) || defined(__aarch64__) || defined(_M_ARM64)
|
|
64
91
|
#include <arm_neon.h>
|
|
@@ -73,14 +100,14 @@ static inline SIMD_Implementation find_simd_implementation(void)
|
|
|
73
100
|
#define HAVE_SIMD_NEON 1
|
|
74
101
|
|
|
75
102
|
// See: https://community.arm.com/arm-community-blogs/b/servers-and-cloud-computing-blog/posts/porting-x86-vector-bitmask-optimizations-to-arm-neon
|
|
76
|
-
|
|
103
|
+
ALWAYS_INLINE(static) uint64_t neon_match_mask(uint8x16_t matches)
|
|
77
104
|
{
|
|
78
105
|
const uint8x8_t res = vshrn_n_u16(vreinterpretq_u16_u8(matches), 4);
|
|
79
106
|
const uint64_t mask = vget_lane_u64(vreinterpret_u64_u8(res), 0);
|
|
80
107
|
return mask & 0x8888888888888888ull;
|
|
81
108
|
}
|
|
82
109
|
|
|
83
|
-
|
|
110
|
+
ALWAYS_INLINE(static) uint64_t compute_chunk_mask_neon(const char *ptr)
|
|
84
111
|
{
|
|
85
112
|
uint8x16_t chunk = vld1q_u8((const unsigned char *)ptr);
|
|
86
113
|
|
|
@@ -93,7 +120,7 @@ static ALWAYS_INLINE() uint64_t compute_chunk_mask_neon(const char *ptr)
|
|
|
93
120
|
return neon_match_mask(needs_escape);
|
|
94
121
|
}
|
|
95
122
|
|
|
96
|
-
|
|
123
|
+
ALWAYS_INLINE(static) int string_scan_simd_neon(const char **ptr, const char *end, uint64_t *mask)
|
|
97
124
|
{
|
|
98
125
|
while (*ptr + sizeof(uint8x16_t) <= end) {
|
|
99
126
|
uint64_t chunk_mask = compute_chunk_mask_neon(*ptr);
|
|
@@ -106,16 +133,6 @@ static ALWAYS_INLINE() int string_scan_simd_neon(const char **ptr, const char *e
|
|
|
106
133
|
return 0;
|
|
107
134
|
}
|
|
108
135
|
|
|
109
|
-
static inline uint8x16x4_t load_uint8x16_4(const unsigned char *table)
|
|
110
|
-
{
|
|
111
|
-
uint8x16x4_t tab;
|
|
112
|
-
tab.val[0] = vld1q_u8(table);
|
|
113
|
-
tab.val[1] = vld1q_u8(table+16);
|
|
114
|
-
tab.val[2] = vld1q_u8(table+32);
|
|
115
|
-
tab.val[3] = vld1q_u8(table+48);
|
|
116
|
-
return tab;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
136
|
#endif /* ARM Neon Support.*/
|
|
120
137
|
|
|
121
138
|
#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)
|
|
@@ -140,7 +157,7 @@ static inline uint8x16x4_t load_uint8x16_4(const unsigned char *table)
|
|
|
140
157
|
#define _mm_cmpgt_epu8(a, b) _mm_xor_si128(_mm_cmple_epu8(a, b), _mm_set1_epi8(-1))
|
|
141
158
|
#define _mm_cmplt_epu8(a, b) _mm_cmpgt_epu8(b, a)
|
|
142
159
|
|
|
143
|
-
static TARGET_SSE2
|
|
160
|
+
ALWAYS_INLINE(static) TARGET_SSE2 int compute_chunk_mask_sse2(const char *ptr)
|
|
144
161
|
{
|
|
145
162
|
__m128i chunk = _mm_loadu_si128((__m128i const*)ptr);
|
|
146
163
|
// Trick: c < 32 || c == 34 can be factored as c ^ 2 < 33
|
|
@@ -151,7 +168,7 @@ static TARGET_SSE2 ALWAYS_INLINE() int compute_chunk_mask_sse2(const char *ptr)
|
|
|
151
168
|
return _mm_movemask_epi8(needs_escape);
|
|
152
169
|
}
|
|
153
170
|
|
|
154
|
-
static TARGET_SSE2
|
|
171
|
+
ALWAYS_INLINE(static) TARGET_SSE2 int string_scan_simd_sse2(const char **ptr, const char *end, int *mask)
|
|
155
172
|
{
|
|
156
173
|
while (*ptr + sizeof(__m128i) <= end) {
|
|
157
174
|
int chunk_mask = compute_chunk_mask_sse2(*ptr);
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
#include <string.h>
|
|
30
30
|
#include <stdint.h>
|
|
31
31
|
|
|
32
|
-
#
|
|
32
|
+
#if JSON_DEBUG
|
|
33
33
|
#include <assert.h>
|
|
34
34
|
#endif
|
|
35
35
|
|
|
@@ -449,7 +449,7 @@ static int filter_special(double fp, char* dest)
|
|
|
449
449
|
* }
|
|
450
450
|
*
|
|
451
451
|
*/
|
|
452
|
-
static int fpconv_dtoa(double d, char dest[
|
|
452
|
+
static int fpconv_dtoa(double d, char dest[32])
|
|
453
453
|
{
|
|
454
454
|
char digits[18];
|
|
455
455
|
|
|
@@ -472,7 +472,7 @@ static int fpconv_dtoa(double d, char dest[28])
|
|
|
472
472
|
int ndigits = grisu2(d, digits, &K);
|
|
473
473
|
|
|
474
474
|
str_len += emit_digits(digits, ndigits, dest + str_len, K, neg);
|
|
475
|
-
#
|
|
475
|
+
#if JSON_DEBUG
|
|
476
476
|
assert(str_len <= 32);
|
|
477
477
|
#endif
|
|
478
478
|
|
data/lib/json/common.rb
CHANGED
|
@@ -156,15 +156,17 @@ module JSON
|
|
|
156
156
|
def generator=(generator) # :nodoc:
|
|
157
157
|
old, $VERBOSE = $VERBOSE, nil
|
|
158
158
|
@generator = generator
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
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
|
|
166
169
|
end
|
|
167
|
-
include modul
|
|
168
170
|
end
|
|
169
171
|
end
|
|
170
172
|
self.state = generator::State
|
|
@@ -550,6 +552,7 @@ module JSON
|
|
|
550
552
|
:create_additions => nil,
|
|
551
553
|
}
|
|
552
554
|
# :call-seq:
|
|
555
|
+
# JSON.unsafe_load(source, options = {}) -> object
|
|
553
556
|
# JSON.unsafe_load(source, proc = nil, options = {}) -> object
|
|
554
557
|
#
|
|
555
558
|
# Returns the Ruby objects created by parsing the given +source+.
|
|
@@ -681,7 +684,12 @@ module JSON
|
|
|
681
684
|
#
|
|
682
685
|
def unsafe_load(source, proc = nil, options = nil)
|
|
683
686
|
opts = if options.nil?
|
|
684
|
-
|
|
687
|
+
if proc && proc.is_a?(Hash)
|
|
688
|
+
options, proc = proc, nil
|
|
689
|
+
options
|
|
690
|
+
else
|
|
691
|
+
_unsafe_load_default_options
|
|
692
|
+
end
|
|
685
693
|
else
|
|
686
694
|
_unsafe_load_default_options.merge(options)
|
|
687
695
|
end
|
|
@@ -709,6 +717,7 @@ module JSON
|
|
|
709
717
|
end
|
|
710
718
|
|
|
711
719
|
# :call-seq:
|
|
720
|
+
# JSON.load(source, options = {}) -> object
|
|
712
721
|
# JSON.load(source, proc = nil, options = {}) -> object
|
|
713
722
|
#
|
|
714
723
|
# Returns the Ruby objects created by parsing the given +source+.
|
|
@@ -845,8 +854,18 @@ module JSON
|
|
|
845
854
|
# @attributes={"type"=>"Admin", "password"=>"0wn3d"}>}
|
|
846
855
|
#
|
|
847
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
|
+
|
|
848
862
|
opts = if options.nil?
|
|
849
|
-
|
|
863
|
+
if proc && proc.is_a?(Hash)
|
|
864
|
+
options, proc = proc, nil
|
|
865
|
+
options
|
|
866
|
+
else
|
|
867
|
+
_load_default_options
|
|
868
|
+
end
|
|
850
869
|
else
|
|
851
870
|
_load_default_options.merge(options)
|
|
852
871
|
end
|
|
@@ -861,7 +880,7 @@ module JSON
|
|
|
861
880
|
end
|
|
862
881
|
end
|
|
863
882
|
|
|
864
|
-
if opts[:allow_blank] && (source.nil? || source.empty?)
|
|
883
|
+
if opts[:allow_blank] && (source.nil? || (String === source && source.empty?))
|
|
865
884
|
source = 'null'
|
|
866
885
|
end
|
|
867
886
|
|
|
@@ -1019,7 +1038,8 @@ module JSON
|
|
|
1019
1038
|
# JSON.new(options = nil, &block)
|
|
1020
1039
|
#
|
|
1021
1040
|
# Argument +options+, if given, contains a \Hash of options for both parsing and generating.
|
|
1022
|
-
# See {Parsing Options}[
|
|
1041
|
+
# See {Parsing Options}[rdoc-ref:JSON@Parsing+Options],
|
|
1042
|
+
# and {Generating Options}[rdoc-ref:JSON@Generating+Options].
|
|
1023
1043
|
#
|
|
1024
1044
|
# For generation, the <tt>strict: true</tt> option is always set. When a Ruby object with no native \JSON counterpart is
|
|
1025
1045
|
# encountered, the block provided to the initialize method is invoked, and must return a Ruby object that has a native
|
|
@@ -1048,7 +1068,7 @@ module JSON
|
|
|
1048
1068
|
options[:as_json] = as_json if as_json
|
|
1049
1069
|
|
|
1050
1070
|
@state = State.new(options).freeze
|
|
1051
|
-
@parser_config = Ext::Parser::Config.new(ParserOptions.prepare(options))
|
|
1071
|
+
@parser_config = Ext::Parser::Config.new(ParserOptions.prepare(options)).freeze
|
|
1052
1072
|
end
|
|
1053
1073
|
|
|
1054
1074
|
# call-seq:
|
|
@@ -1057,7 +1077,7 @@ module JSON
|
|
|
1057
1077
|
#
|
|
1058
1078
|
# Serialize the given object into a \JSON document.
|
|
1059
1079
|
def dump(object, io = nil)
|
|
1060
|
-
@state.
|
|
1080
|
+
@state.generate(object, io)
|
|
1061
1081
|
end
|
|
1062
1082
|
alias_method :generate, :dump
|
|
1063
1083
|
|
|
@@ -1078,6 +1098,30 @@ module JSON
|
|
|
1078
1098
|
load(File.read(path, encoding: Encoding::UTF_8))
|
|
1079
1099
|
end
|
|
1080
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
|
|
1081
1125
|
end
|
|
1082
1126
|
|
|
1083
1127
|
module ::Kernel
|
|
@@ -1123,3 +1167,7 @@ module ::Kernel
|
|
|
1123
1167
|
JSON[object, opts]
|
|
1124
1168
|
end
|
|
1125
1169
|
end
|
|
1170
|
+
|
|
1171
|
+
class Object
|
|
1172
|
+
include JSON::GeneratorMethods
|
|
1173
|
+
end
|
|
@@ -9,7 +9,7 @@ module JSON
|
|
|
9
9
|
# Instantiates a new State object, configured by _opts_.
|
|
10
10
|
#
|
|
11
11
|
# Argument +opts+, if given, contains a \Hash of options for the generation.
|
|
12
|
-
# See {Generating Options}[
|
|
12
|
+
# See {Generating Options}[rdoc-ref:JSON@Generating+Options].
|
|
13
13
|
def initialize(opts = nil)
|
|
14
14
|
if opts && !opts.empty?
|
|
15
15
|
configure(opts)
|
|
@@ -211,7 +211,14 @@ module JSON
|
|
|
211
211
|
|
|
212
212
|
# This integer returns the current depth data structure nesting in the
|
|
213
213
|
# generated JSON.
|
|
214
|
-
|
|
214
|
+
attr_reader :depth
|
|
215
|
+
|
|
216
|
+
def depth=(depth)
|
|
217
|
+
if depth.negative?
|
|
218
|
+
raise ArgumentError, "depth must be >= 0 (got #{depth})"
|
|
219
|
+
end
|
|
220
|
+
@depth = depth
|
|
221
|
+
end
|
|
215
222
|
|
|
216
223
|
def check_max_nesting # :nodoc:
|
|
217
224
|
return if @max_nesting.zero?
|
|
@@ -260,6 +267,11 @@ module JSON
|
|
|
260
267
|
else
|
|
261
268
|
raise TypeError, "can't convert #{opts.class} into Hash"
|
|
262
269
|
end
|
|
270
|
+
|
|
271
|
+
if opts[:depth]&.negative?
|
|
272
|
+
raise ArgumentError, "depth must be >= 0 (got #{opts[:depth]})"
|
|
273
|
+
end
|
|
274
|
+
|
|
263
275
|
opts.each do |key, value|
|
|
264
276
|
instance_variable_set "@#{key}", value
|
|
265
277
|
end
|
|
@@ -312,8 +324,8 @@ module JSON
|
|
|
312
324
|
def to_h
|
|
313
325
|
result = {}
|
|
314
326
|
instance_variables.each do |iv|
|
|
315
|
-
|
|
316
|
-
result[
|
|
327
|
+
key = iv.to_s[1..-1]
|
|
328
|
+
result[key.to_sym] = instance_variable_get(iv)
|
|
317
329
|
end
|
|
318
330
|
|
|
319
331
|
if result[:allow_duplicate_key].nil?
|
|
@@ -330,6 +342,9 @@ module JSON
|
|
|
330
342
|
# created this method raises a
|
|
331
343
|
# GeneratorError exception.
|
|
332
344
|
def generate(obj, anIO = nil)
|
|
345
|
+
return dup.generate(obj, anIO) if frozen?
|
|
346
|
+
|
|
347
|
+
depth = @depth
|
|
333
348
|
if @indent.empty? and @space.empty? and @space_before.empty? and @object_nl.empty? and @array_nl.empty? and
|
|
334
349
|
!@ascii_only and !@script_safe and @max_nesting == 0 and (!@strict || Symbol === obj)
|
|
335
350
|
result = generate_json(obj, ''.dup)
|
|
@@ -346,14 +361,8 @@ module JSON
|
|
|
346
361
|
else
|
|
347
362
|
result
|
|
348
363
|
end
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
def generate_new(obj, anIO = nil) # :nodoc:
|
|
352
|
-
dup.generate(obj, anIO)
|
|
353
|
-
end
|
|
354
|
-
|
|
355
|
-
private def initialize_copy(_orig)
|
|
356
|
-
@depth = 0
|
|
364
|
+
ensure
|
|
365
|
+
@depth = depth unless frozen?
|
|
357
366
|
end
|
|
358
367
|
|
|
359
368
|
# Handles @allow_nan, @buffer_initial_length, other ivars must be the default value (see above)
|
|
@@ -494,17 +503,15 @@ module JSON
|
|
|
494
503
|
# _depth_ is used to find out nesting depth, to indent accordingly.
|
|
495
504
|
def to_json(state = nil, *)
|
|
496
505
|
state = State.from_state(state)
|
|
506
|
+
depth = state.depth
|
|
497
507
|
state.check_max_nesting
|
|
498
508
|
json_transform(state)
|
|
509
|
+
ensure
|
|
510
|
+
state.depth = depth
|
|
499
511
|
end
|
|
500
512
|
|
|
501
513
|
private
|
|
502
514
|
|
|
503
|
-
def json_shift(state)
|
|
504
|
-
state.object_nl.empty? or return ''
|
|
505
|
-
state.indent * state.depth
|
|
506
|
-
end
|
|
507
|
-
|
|
508
515
|
def json_transform(state)
|
|
509
516
|
depth = state.depth += 1
|
|
510
517
|
|
|
@@ -559,17 +566,19 @@ module JSON
|
|
|
559
566
|
raise GeneratorError.new("#{value.class} returned by #{state.as_json} not allowed in JSON", value)
|
|
560
567
|
end
|
|
561
568
|
result << value.to_json(state)
|
|
569
|
+
state.depth = depth
|
|
562
570
|
else
|
|
563
571
|
raise GeneratorError.new("#{value.class} not allowed in JSON", value)
|
|
564
572
|
end
|
|
565
573
|
elsif value.respond_to?(:to_json)
|
|
566
574
|
result << value.to_json(state)
|
|
575
|
+
state.depth = depth
|
|
567
576
|
else
|
|
568
577
|
result << %{"#{String(value)}"}
|
|
569
578
|
end
|
|
570
579
|
first = false
|
|
571
580
|
}
|
|
572
|
-
depth
|
|
581
|
+
depth -= 1
|
|
573
582
|
unless first
|
|
574
583
|
result << state.object_nl
|
|
575
584
|
result << state.indent * depth if indent
|
|
@@ -586,8 +595,11 @@ module JSON
|
|
|
586
595
|
# produced JSON string output further.
|
|
587
596
|
def to_json(state = nil, *)
|
|
588
597
|
state = State.from_state(state)
|
|
598
|
+
depth = state.depth
|
|
589
599
|
state.check_max_nesting
|
|
590
600
|
json_transform(state)
|
|
601
|
+
ensure
|
|
602
|
+
state.depth = depth
|
|
591
603
|
end
|
|
592
604
|
|
|
593
605
|
private
|
|
@@ -625,12 +637,13 @@ module JSON
|
|
|
625
637
|
end
|
|
626
638
|
elsif value.respond_to?(:to_json)
|
|
627
639
|
result << value.to_json(state)
|
|
640
|
+
state.depth = depth
|
|
628
641
|
else
|
|
629
642
|
result << %{"#{String(value)}"}
|
|
630
643
|
end
|
|
631
644
|
first = false
|
|
632
645
|
}
|
|
633
|
-
depth
|
|
646
|
+
depth -= 1
|
|
634
647
|
result << state.array_nl
|
|
635
648
|
result << state.indent * depth if indent
|
|
636
649
|
result << ']'
|
|
@@ -655,6 +668,9 @@ module JSON
|
|
|
655
668
|
if casted_value.equal?(self)
|
|
656
669
|
raise GeneratorError.new("#{self} not allowed in JSON", self)
|
|
657
670
|
end
|
|
671
|
+
unless Generator.native_type?(casted_value)
|
|
672
|
+
raise GeneratorError.new("#{casted_value.class} returned by #{state.as_json} not allowed in JSON", casted_value)
|
|
673
|
+
end
|
|
658
674
|
|
|
659
675
|
state.check_max_nesting
|
|
660
676
|
state.depth += 1
|
data/lib/json/version.rb
CHANGED
data/lib/json.rb
CHANGED
|
@@ -6,6 +6,15 @@ require 'json/common'
|
|
|
6
6
|
#
|
|
7
7
|
# \JSON is a lightweight data-interchange format.
|
|
8
8
|
#
|
|
9
|
+
# \JSON is easy for us humans to read and write,
|
|
10
|
+
# and equally simple for machines to read (parse) and write (generate).
|
|
11
|
+
#
|
|
12
|
+
# \JSON is language-independent, making it an ideal interchange format
|
|
13
|
+
# for applications in differing programming languages
|
|
14
|
+
# and on differing operating systems.
|
|
15
|
+
#
|
|
16
|
+
# == \JSON Values
|
|
17
|
+
#
|
|
9
18
|
# A \JSON value is one of the following:
|
|
10
19
|
# - Double-quoted text: <tt>"foo"</tt>.
|
|
11
20
|
# - Number: +1+, +1.0+, +2.0e2+.
|
|
@@ -173,6 +182,30 @@ require 'json/common'
|
|
|
173
182
|
# When enabled:
|
|
174
183
|
# JSON.parse('[1,]', allow_trailing_comma: true) # => [1]
|
|
175
184
|
#
|
|
185
|
+
# ---
|
|
186
|
+
#
|
|
187
|
+
# Option +allow_control_characters+ (boolean) specifies whether to allow
|
|
188
|
+
# unescaped ASCII control characters, such as newlines, in strings;
|
|
189
|
+
# defaults to +false+.
|
|
190
|
+
#
|
|
191
|
+
# With the default, +false+:
|
|
192
|
+
# JSON.parse(%{"Hello\nWorld"}) # invalid ASCII control character in string (JSON::ParserError)
|
|
193
|
+
#
|
|
194
|
+
# When enabled:
|
|
195
|
+
# JSON.parse(%{"Hello\nWorld"}, allow_control_characters: true) # => "Hello\nWorld"
|
|
196
|
+
#
|
|
197
|
+
# ---
|
|
198
|
+
#
|
|
199
|
+
# Option +allow_invalid_escape+ (boolean) specifies whether to ignore backslahes that are followed
|
|
200
|
+
# by an invalid escape character in strings;
|
|
201
|
+
# defaults to +false+.
|
|
202
|
+
#
|
|
203
|
+
# With the default, +false+:
|
|
204
|
+
# JSON.parse('"Hell\o"') # invalid escape character in string (JSON::ParserError)
|
|
205
|
+
#
|
|
206
|
+
# When enabled:
|
|
207
|
+
# JSON.parse('"Hell\o"', allow_invalid_escape: true) # => "Hello"
|
|
208
|
+
#
|
|
176
209
|
# ====== Output Options
|
|
177
210
|
#
|
|
178
211
|
# Option +freeze+ (boolean) specifies whether the returned objects will be frozen;
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: json
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.19.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Florian Frank
|
|
@@ -84,7 +84,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
84
84
|
- !ruby/object:Gem::Version
|
|
85
85
|
version: '0'
|
|
86
86
|
requirements: []
|
|
87
|
-
rubygems_version:
|
|
87
|
+
rubygems_version: 4.0.3
|
|
88
88
|
specification_version: 4
|
|
89
89
|
summary: JSON Implementation for Ruby
|
|
90
90
|
test_files: []
|