json 2.12.2 → 3.0.0
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 +222 -8
- data/LEGAL +12 -0
- data/README.md +34 -87
- data/ext/json/ext/fbuffer/fbuffer.h +75 -86
- data/ext/json/ext/generator/extconf.rb +5 -26
- data/ext/json/ext/generator/generator.c +560 -688
- data/ext/json/ext/json.h +196 -0
- data/ext/json/ext/parser/extconf.rb +34 -2
- data/ext/json/ext/parser/parser.c +2177 -673
- data/ext/json/ext/simd/conf.rb +24 -0
- data/ext/json/ext/simd/simd.h +208 -0
- data/ext/json/ext/vendor/fast_float_parser.h +814 -0
- data/ext/json/ext/vendor/fpconv.c +13 -12
- data/json.gemspec +2 -3
- data/lib/json/common.rb +200 -389
- data/lib/json/ext/generator/state.rb +8 -37
- data/lib/json/ext.rb +25 -1
- data/lib/json/truffle_ruby/generator.rb +186 -128
- data/lib/json/version.rb +1 -1
- data/lib/json.rb +107 -242
- metadata +7 -19
- data/ext/json/ext/generator/simd.h +0 -112
- data/lib/json/add/bigdecimal.rb +0 -58
- data/lib/json/add/complex.rb +0 -51
- data/lib/json/add/core.rb +0 -12
- data/lib/json/add/date.rb +0 -54
- data/lib/json/add/date_time.rb +0 -67
- data/lib/json/add/exception.rb +0 -49
- data/lib/json/add/ostruct.rb +0 -54
- data/lib/json/add/range.rb +0 -54
- data/lib/json/add/rational.rb +0 -49
- data/lib/json/add/regexp.rb +0 -48
- data/lib/json/add/set.rb +0 -48
- data/lib/json/add/struct.rb +0 -52
- data/lib/json/add/symbol.rb +0 -52
- data/lib/json/add/time.rb +0 -52
- data/lib/json/generic_object.rb +0 -75
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+.
|
|
@@ -112,9 +121,11 @@ require 'json/common'
|
|
|
112
121
|
# ====== Input Options
|
|
113
122
|
#
|
|
114
123
|
# Option +max_nesting+ (\Integer) specifies the maximum nesting depth allowed;
|
|
115
|
-
# defaults to +100+;
|
|
124
|
+
# defaults to +100+;
|
|
125
|
+
# You can set it to +false+ to disable depth checking entirely, but that is dangerous
|
|
126
|
+
# when parsing untrusted input.
|
|
116
127
|
#
|
|
117
|
-
# With the default, +
|
|
128
|
+
# With the default, +100+:
|
|
118
129
|
# source = '[0, [1, [2, [3]]]]'
|
|
119
130
|
# ruby = JSON.parse(source)
|
|
120
131
|
# ruby # => [0, [1, [2, [3]]]]
|
|
@@ -127,6 +138,18 @@ require 'json/common'
|
|
|
127
138
|
#
|
|
128
139
|
# ---
|
|
129
140
|
#
|
|
141
|
+
# Option +allow_duplicate_key+ specifies whether duplicate keys in objects
|
|
142
|
+
# should be ignored or cause an error to be raised:
|
|
143
|
+
#
|
|
144
|
+
# When set to +false+, the default:
|
|
145
|
+
# JSON.parse('{"a": 1, "a":2}') => duplicate key at line 1 column 1 (JSON::ParserError)
|
|
146
|
+
#
|
|
147
|
+
# When set to +true+:
|
|
148
|
+
# # The last value is used.
|
|
149
|
+
# JSON.parse('{"a": 1, "a":2}', allow_duplicate_key: true) => {"a" => 2}
|
|
150
|
+
#
|
|
151
|
+
# ---
|
|
152
|
+
#
|
|
130
153
|
# Option +allow_nan+ (boolean) specifies whether to allow
|
|
131
154
|
# NaN, Infinity, and MinusInfinity in +source+;
|
|
132
155
|
# defaults to +false+.
|
|
@@ -143,8 +166,59 @@ require 'json/common'
|
|
|
143
166
|
# ruby = JSON.parse(source, {allow_nan: true})
|
|
144
167
|
# ruby # => [NaN, Infinity, -Infinity]
|
|
145
168
|
#
|
|
169
|
+
# ---
|
|
170
|
+
#
|
|
171
|
+
# Option +allow_trailing_comma+ (boolean) specifies whether to allow
|
|
172
|
+
# trailing commas in objects and arrays;
|
|
173
|
+
# defaults to +false+.
|
|
174
|
+
#
|
|
175
|
+
# With the default, +false+:
|
|
176
|
+
# JSON.parse('[1,]') # unexpected character: ']' at line 1 column 4 (JSON::ParserError)
|
|
177
|
+
#
|
|
178
|
+
# When enabled:
|
|
179
|
+
# JSON.parse('[1,]', allow_trailing_comma: true) # => [1]
|
|
180
|
+
#
|
|
181
|
+
# ---
|
|
182
|
+
#
|
|
183
|
+
# Option +allow_comments+ (boolean) specifies whether to allow
|
|
184
|
+
# JavaScript style comments (either <tt>// comment</tt> or <tt>/* comment */</tt>);
|
|
185
|
+
# defaults to +false+.
|
|
186
|
+
#
|
|
187
|
+
# When set to +false+, the default:
|
|
188
|
+
# JSON.parse('/* comment */ {"a": 1, "a":2}') # unexpected character: '/' at line 1 column 1 (JSON::ParserError)
|
|
189
|
+
#
|
|
190
|
+
# When set to +true+, comments are ignored:
|
|
191
|
+
# JSON.parse('/* comment */ {"a": 1, "a":2} // more comment') # => {"a" => 2}
|
|
192
|
+
#
|
|
193
|
+
# ---
|
|
194
|
+
#
|
|
195
|
+
# Option +allow_control_characters+ (boolean) specifies whether to allow
|
|
196
|
+
# unescaped ASCII control characters, such as newlines, in strings;
|
|
197
|
+
# defaults to +false+.
|
|
198
|
+
#
|
|
199
|
+
# With the default, +false+:
|
|
200
|
+
# JSON.parse(%{"Hello\nWorld"}) # invalid ASCII control character in string (JSON::ParserError)
|
|
201
|
+
#
|
|
202
|
+
# When enabled:
|
|
203
|
+
# JSON.parse(%{"Hello\nWorld"}, allow_control_characters: true) # => "Hello\nWorld"
|
|
204
|
+
#
|
|
205
|
+
# ---
|
|
206
|
+
#
|
|
207
|
+
# Option +allow_invalid_escape+ (boolean) specifies whether to ignore backslahes that are followed
|
|
208
|
+
# by an invalid escape character in strings;
|
|
209
|
+
# defaults to +false+.
|
|
210
|
+
#
|
|
211
|
+
# With the default, +false+:
|
|
212
|
+
# JSON.parse('"Hell\o"') # invalid escape character in string (JSON::ParserError)
|
|
213
|
+
#
|
|
214
|
+
# When enabled:
|
|
215
|
+
# JSON.parse('"Hell\o"', allow_invalid_escape: true) # => "Hello"
|
|
216
|
+
#
|
|
146
217
|
# ====== Output Options
|
|
147
218
|
#
|
|
219
|
+
# Option +freeze+ (boolean) specifies whether the returned objects will be frozen;
|
|
220
|
+
# defaults to +false+.
|
|
221
|
+
#
|
|
148
222
|
# Option +symbolize_names+ (boolean) specifies whether returned \Hash keys
|
|
149
223
|
# should be Symbols;
|
|
150
224
|
# defaults to +false+ (use Strings).
|
|
@@ -185,11 +259,6 @@ require 'json/common'
|
|
|
185
259
|
# ruby = JSON.parse(source, {array_class: Set})
|
|
186
260
|
# ruby # => #<Set: {"foo", 1.0, true, false, nil}>
|
|
187
261
|
#
|
|
188
|
-
# ---
|
|
189
|
-
#
|
|
190
|
-
# Option +create_additions+ (boolean) specifies whether to use \JSON additions in parsing.
|
|
191
|
-
# See {\JSON Additions}[#module-JSON-label-JSON+Additions].
|
|
192
|
-
#
|
|
193
262
|
# === Generating \JSON
|
|
194
263
|
#
|
|
195
264
|
# To generate a Ruby \String containing \JSON data,
|
|
@@ -269,8 +338,22 @@ require 'json/common'
|
|
|
269
338
|
# JSON.generate(JSON::MinusInfinity)
|
|
270
339
|
#
|
|
271
340
|
# Allow:
|
|
272
|
-
# ruby = [Float::
|
|
273
|
-
# JSON.generate(ruby, allow_nan: true) # => '[NaN,Infinity,-Infinity]'
|
|
341
|
+
# ruby = [Float::NAN, Float::INFINITY, JSON::NaN, JSON::Infinity, JSON::MinusInfinity]
|
|
342
|
+
# JSON.generate(ruby, allow_nan: true) # => '[NaN,Infinity,NaN,Infinity,-Infinity]'
|
|
343
|
+
#
|
|
344
|
+
# ---
|
|
345
|
+
#
|
|
346
|
+
# Option +allow_duplicate_key+ (boolean) specifies whether
|
|
347
|
+
# hashes with duplicate keys should be allowed or produce an error.
|
|
348
|
+
# defaults to emit a deprecation warning.
|
|
349
|
+
#
|
|
350
|
+
# With the default, <tt>false</tt>:
|
|
351
|
+
# JSON.generate({ foo: 1, "foo" => 2 })
|
|
352
|
+
# # detected duplicate key "foo" in {foo: 1, "foo" => 2} (JSON::GeneratorError)
|
|
353
|
+
#
|
|
354
|
+
# With <tt>true</tt>
|
|
355
|
+
# JSON.generate({ foo: 1, "foo" => 2 }, allow_duplicate_key: true)
|
|
356
|
+
# # => '{"foo":1,"foo":2}'
|
|
274
357
|
#
|
|
275
358
|
# ---
|
|
276
359
|
#
|
|
@@ -285,6 +368,16 @@ require 'json/common'
|
|
|
285
368
|
# # Raises JSON::NestingError (nesting of 2 is too deep):
|
|
286
369
|
# JSON.generate(obj, max_nesting: 2)
|
|
287
370
|
#
|
|
371
|
+
# With +false+:
|
|
372
|
+
# obj = []
|
|
373
|
+
# obj[0] = obj
|
|
374
|
+
# # Raises SystemStackError: stack level too deep
|
|
375
|
+
# JSON.generate(obj, max_nesting: false)
|
|
376
|
+
#
|
|
377
|
+
# Setting +max_nesting+ to +false+ or a very large number can lead to a stack overflow
|
|
378
|
+
# which may leave the process in an unrecoverable state.
|
|
379
|
+
# It is highly discouraged.
|
|
380
|
+
#
|
|
288
381
|
# ====== Escaping Options
|
|
289
382
|
#
|
|
290
383
|
# Options +script_safe+ (boolean) specifies wether <tt>'\u2028'</tt>, <tt>'\u2029'</tt>
|
|
@@ -309,7 +402,6 @@ require 'json/common'
|
|
|
309
402
|
# to be inserted after each \JSON object; defaults to the empty \String, <tt>''</tt>.
|
|
310
403
|
# - Option +indent+ (\String) specifies the string (usually spaces) to be
|
|
311
404
|
# used for indentation; defaults to the empty \String, <tt>''</tt>;
|
|
312
|
-
# defaults to the empty \String, <tt>''</tt>;
|
|
313
405
|
# has no effect unless options +array_nl+ or +object_nl+ specify newlines.
|
|
314
406
|
# - Option +space+ (\String) specifies a string (usually a space) to be
|
|
315
407
|
# inserted after the colon in each \JSON object's pair;
|
|
@@ -317,6 +409,11 @@ require 'json/common'
|
|
|
317
409
|
# - Option +space_before+ (\String) specifies a string (usually a space) to be
|
|
318
410
|
# inserted before the colon in each \JSON object's pair;
|
|
319
411
|
# defaults to the empty \String, <tt>''</tt>.
|
|
412
|
+
# - Option +sort_keys+ (boolean or \Proc) controls whether and how the keys of a
|
|
413
|
+
# hash are sorted when generating the output; defaults to <tt>false</tt>.
|
|
414
|
+
# When +true+, keys are sorted lexicographically. When a \Proc, it receives
|
|
415
|
+
# the entire \Hash and must return a \Hash with its pairs in the desired
|
|
416
|
+
# order, allowing for arbitrary sort orders.
|
|
320
417
|
#
|
|
321
418
|
# In this example, +obj+ is used first to generate the shortest
|
|
322
419
|
# \JSON data (no whitespace), then again with all formatting options
|
|
@@ -349,238 +446,6 @@ require 'json/common'
|
|
|
349
446
|
# }
|
|
350
447
|
# }
|
|
351
448
|
#
|
|
352
|
-
# == \JSON Additions
|
|
353
|
-
#
|
|
354
|
-
# When you "round trip" a non-\String object from Ruby to \JSON and back,
|
|
355
|
-
# you have a new \String, instead of the object you began with:
|
|
356
|
-
# ruby0 = Range.new(0, 2)
|
|
357
|
-
# json = JSON.generate(ruby0)
|
|
358
|
-
# json # => '0..2"'
|
|
359
|
-
# ruby1 = JSON.parse(json)
|
|
360
|
-
# ruby1 # => '0..2'
|
|
361
|
-
# ruby1.class # => String
|
|
362
|
-
#
|
|
363
|
-
# You can use \JSON _additions_ to preserve the original object.
|
|
364
|
-
# The addition is an extension of a ruby class, so that:
|
|
365
|
-
# - \JSON.generate stores more information in the \JSON string.
|
|
366
|
-
# - \JSON.parse, called with option +create_additions+,
|
|
367
|
-
# uses that information to create a proper Ruby object.
|
|
368
|
-
#
|
|
369
|
-
# This example shows a \Range being generated into \JSON
|
|
370
|
-
# and parsed back into Ruby, both without and with
|
|
371
|
-
# the addition for \Range:
|
|
372
|
-
# ruby = Range.new(0, 2)
|
|
373
|
-
# # This passage does not use the addition for Range.
|
|
374
|
-
# json0 = JSON.generate(ruby)
|
|
375
|
-
# ruby0 = JSON.parse(json0)
|
|
376
|
-
# # This passage uses the addition for Range.
|
|
377
|
-
# require 'json/add/range'
|
|
378
|
-
# json1 = JSON.generate(ruby)
|
|
379
|
-
# ruby1 = JSON.parse(json1, create_additions: true)
|
|
380
|
-
# # Make a nice display.
|
|
381
|
-
# display = <<~EOT
|
|
382
|
-
# Generated JSON:
|
|
383
|
-
# Without addition: #{json0} (#{json0.class})
|
|
384
|
-
# With addition: #{json1} (#{json1.class})
|
|
385
|
-
# Parsed JSON:
|
|
386
|
-
# Without addition: #{ruby0.inspect} (#{ruby0.class})
|
|
387
|
-
# With addition: #{ruby1.inspect} (#{ruby1.class})
|
|
388
|
-
# EOT
|
|
389
|
-
# puts display
|
|
390
|
-
#
|
|
391
|
-
# This output shows the different results:
|
|
392
|
-
# Generated JSON:
|
|
393
|
-
# Without addition: "0..2" (String)
|
|
394
|
-
# With addition: {"json_class":"Range","a":[0,2,false]} (String)
|
|
395
|
-
# Parsed JSON:
|
|
396
|
-
# Without addition: "0..2" (String)
|
|
397
|
-
# With addition: 0..2 (Range)
|
|
398
|
-
#
|
|
399
|
-
# The \JSON module includes additions for certain classes.
|
|
400
|
-
# You can also craft custom additions.
|
|
401
|
-
# See {Custom \JSON Additions}[#module-JSON-label-Custom+JSON+Additions].
|
|
402
|
-
#
|
|
403
|
-
# === Built-in Additions
|
|
404
|
-
#
|
|
405
|
-
# The \JSON module includes additions for certain classes.
|
|
406
|
-
# To use an addition, +require+ its source:
|
|
407
|
-
# - BigDecimal: <tt>require 'json/add/bigdecimal'</tt>
|
|
408
|
-
# - Complex: <tt>require 'json/add/complex'</tt>
|
|
409
|
-
# - Date: <tt>require 'json/add/date'</tt>
|
|
410
|
-
# - DateTime: <tt>require 'json/add/date_time'</tt>
|
|
411
|
-
# - Exception: <tt>require 'json/add/exception'</tt>
|
|
412
|
-
# - OpenStruct: <tt>require 'json/add/ostruct'</tt>
|
|
413
|
-
# - Range: <tt>require 'json/add/range'</tt>
|
|
414
|
-
# - Rational: <tt>require 'json/add/rational'</tt>
|
|
415
|
-
# - Regexp: <tt>require 'json/add/regexp'</tt>
|
|
416
|
-
# - Set: <tt>require 'json/add/set'</tt>
|
|
417
|
-
# - Struct: <tt>require 'json/add/struct'</tt>
|
|
418
|
-
# - Symbol: <tt>require 'json/add/symbol'</tt>
|
|
419
|
-
# - Time: <tt>require 'json/add/time'</tt>
|
|
420
|
-
#
|
|
421
|
-
# To reduce punctuation clutter, the examples below
|
|
422
|
-
# show the generated \JSON via +puts+, rather than the usual +inspect+,
|
|
423
|
-
#
|
|
424
|
-
# \BigDecimal:
|
|
425
|
-
# require 'json/add/bigdecimal'
|
|
426
|
-
# ruby0 = BigDecimal(0) # 0.0
|
|
427
|
-
# json = JSON.generate(ruby0) # {"json_class":"BigDecimal","b":"27:0.0"}
|
|
428
|
-
# ruby1 = JSON.parse(json, create_additions: true) # 0.0
|
|
429
|
-
# ruby1.class # => BigDecimal
|
|
430
|
-
#
|
|
431
|
-
# \Complex:
|
|
432
|
-
# require 'json/add/complex'
|
|
433
|
-
# ruby0 = Complex(1+0i) # 1+0i
|
|
434
|
-
# json = JSON.generate(ruby0) # {"json_class":"Complex","r":1,"i":0}
|
|
435
|
-
# ruby1 = JSON.parse(json, create_additions: true) # 1+0i
|
|
436
|
-
# ruby1.class # Complex
|
|
437
|
-
#
|
|
438
|
-
# \Date:
|
|
439
|
-
# require 'json/add/date'
|
|
440
|
-
# ruby0 = Date.today # 2020-05-02
|
|
441
|
-
# json = JSON.generate(ruby0) # {"json_class":"Date","y":2020,"m":5,"d":2,"sg":2299161.0}
|
|
442
|
-
# ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02
|
|
443
|
-
# ruby1.class # Date
|
|
444
|
-
#
|
|
445
|
-
# \DateTime:
|
|
446
|
-
# require 'json/add/date_time'
|
|
447
|
-
# ruby0 = DateTime.now # 2020-05-02T10:38:13-05:00
|
|
448
|
-
# json = JSON.generate(ruby0) # {"json_class":"DateTime","y":2020,"m":5,"d":2,"H":10,"M":38,"S":13,"of":"-5/24","sg":2299161.0}
|
|
449
|
-
# ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02T10:38:13-05:00
|
|
450
|
-
# ruby1.class # DateTime
|
|
451
|
-
#
|
|
452
|
-
# \Exception (and its subclasses including \RuntimeError):
|
|
453
|
-
# require 'json/add/exception'
|
|
454
|
-
# ruby0 = Exception.new('A message') # A message
|
|
455
|
-
# json = JSON.generate(ruby0) # {"json_class":"Exception","m":"A message","b":null}
|
|
456
|
-
# ruby1 = JSON.parse(json, create_additions: true) # A message
|
|
457
|
-
# ruby1.class # Exception
|
|
458
|
-
# ruby0 = RuntimeError.new('Another message') # Another message
|
|
459
|
-
# json = JSON.generate(ruby0) # {"json_class":"RuntimeError","m":"Another message","b":null}
|
|
460
|
-
# ruby1 = JSON.parse(json, create_additions: true) # Another message
|
|
461
|
-
# ruby1.class # RuntimeError
|
|
462
|
-
#
|
|
463
|
-
# \OpenStruct:
|
|
464
|
-
# require 'json/add/ostruct'
|
|
465
|
-
# ruby0 = OpenStruct.new(name: 'Matz', language: 'Ruby') # #<OpenStruct name="Matz", language="Ruby">
|
|
466
|
-
# json = JSON.generate(ruby0) # {"json_class":"OpenStruct","t":{"name":"Matz","language":"Ruby"}}
|
|
467
|
-
# ruby1 = JSON.parse(json, create_additions: true) # #<OpenStruct name="Matz", language="Ruby">
|
|
468
|
-
# ruby1.class # OpenStruct
|
|
469
|
-
#
|
|
470
|
-
# \Range:
|
|
471
|
-
# require 'json/add/range'
|
|
472
|
-
# ruby0 = Range.new(0, 2) # 0..2
|
|
473
|
-
# json = JSON.generate(ruby0) # {"json_class":"Range","a":[0,2,false]}
|
|
474
|
-
# ruby1 = JSON.parse(json, create_additions: true) # 0..2
|
|
475
|
-
# ruby1.class # Range
|
|
476
|
-
#
|
|
477
|
-
# \Rational:
|
|
478
|
-
# require 'json/add/rational'
|
|
479
|
-
# ruby0 = Rational(1, 3) # 1/3
|
|
480
|
-
# json = JSON.generate(ruby0) # {"json_class":"Rational","n":1,"d":3}
|
|
481
|
-
# ruby1 = JSON.parse(json, create_additions: true) # 1/3
|
|
482
|
-
# ruby1.class # Rational
|
|
483
|
-
#
|
|
484
|
-
# \Regexp:
|
|
485
|
-
# require 'json/add/regexp'
|
|
486
|
-
# ruby0 = Regexp.new('foo') # (?-mix:foo)
|
|
487
|
-
# json = JSON.generate(ruby0) # {"json_class":"Regexp","o":0,"s":"foo"}
|
|
488
|
-
# ruby1 = JSON.parse(json, create_additions: true) # (?-mix:foo)
|
|
489
|
-
# ruby1.class # Regexp
|
|
490
|
-
#
|
|
491
|
-
# \Set:
|
|
492
|
-
# require 'json/add/set'
|
|
493
|
-
# ruby0 = Set.new([0, 1, 2]) # #<Set: {0, 1, 2}>
|
|
494
|
-
# json = JSON.generate(ruby0) # {"json_class":"Set","a":[0,1,2]}
|
|
495
|
-
# ruby1 = JSON.parse(json, create_additions: true) # #<Set: {0, 1, 2}>
|
|
496
|
-
# ruby1.class # Set
|
|
497
|
-
#
|
|
498
|
-
# \Struct:
|
|
499
|
-
# require 'json/add/struct'
|
|
500
|
-
# Customer = Struct.new(:name, :address) # Customer
|
|
501
|
-
# ruby0 = Customer.new("Dave", "123 Main") # #<struct Customer name="Dave", address="123 Main">
|
|
502
|
-
# json = JSON.generate(ruby0) # {"json_class":"Customer","v":["Dave","123 Main"]}
|
|
503
|
-
# ruby1 = JSON.parse(json, create_additions: true) # #<struct Customer name="Dave", address="123 Main">
|
|
504
|
-
# ruby1.class # Customer
|
|
505
|
-
#
|
|
506
|
-
# \Symbol:
|
|
507
|
-
# require 'json/add/symbol'
|
|
508
|
-
# ruby0 = :foo # foo
|
|
509
|
-
# json = JSON.generate(ruby0) # {"json_class":"Symbol","s":"foo"}
|
|
510
|
-
# ruby1 = JSON.parse(json, create_additions: true) # foo
|
|
511
|
-
# ruby1.class # Symbol
|
|
512
|
-
#
|
|
513
|
-
# \Time:
|
|
514
|
-
# require 'json/add/time'
|
|
515
|
-
# ruby0 = Time.now # 2020-05-02 11:28:26 -0500
|
|
516
|
-
# json = JSON.generate(ruby0) # {"json_class":"Time","s":1588436906,"n":840560000}
|
|
517
|
-
# ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02 11:28:26 -0500
|
|
518
|
-
# ruby1.class # Time
|
|
519
|
-
#
|
|
520
|
-
#
|
|
521
|
-
# === Custom \JSON Additions
|
|
522
|
-
#
|
|
523
|
-
# In addition to the \JSON additions provided,
|
|
524
|
-
# you can craft \JSON additions of your own,
|
|
525
|
-
# either for Ruby built-in classes or for user-defined classes.
|
|
526
|
-
#
|
|
527
|
-
# Here's a user-defined class +Foo+:
|
|
528
|
-
# class Foo
|
|
529
|
-
# attr_accessor :bar, :baz
|
|
530
|
-
# def initialize(bar, baz)
|
|
531
|
-
# self.bar = bar
|
|
532
|
-
# self.baz = baz
|
|
533
|
-
# end
|
|
534
|
-
# end
|
|
535
|
-
#
|
|
536
|
-
# Here's the \JSON addition for it:
|
|
537
|
-
# # Extend class Foo with JSON addition.
|
|
538
|
-
# class Foo
|
|
539
|
-
# # Serialize Foo object with its class name and arguments
|
|
540
|
-
# def to_json(*args)
|
|
541
|
-
# {
|
|
542
|
-
# JSON.create_id => self.class.name,
|
|
543
|
-
# 'a' => [ bar, baz ]
|
|
544
|
-
# }.to_json(*args)
|
|
545
|
-
# end
|
|
546
|
-
# # Deserialize JSON string by constructing new Foo object with arguments.
|
|
547
|
-
# def self.json_create(object)
|
|
548
|
-
# new(*object['a'])
|
|
549
|
-
# end
|
|
550
|
-
# end
|
|
551
|
-
#
|
|
552
|
-
# Demonstration:
|
|
553
|
-
# require 'json'
|
|
554
|
-
# # This Foo object has no custom addition.
|
|
555
|
-
# foo0 = Foo.new(0, 1)
|
|
556
|
-
# json0 = JSON.generate(foo0)
|
|
557
|
-
# obj0 = JSON.parse(json0)
|
|
558
|
-
# # Lood the custom addition.
|
|
559
|
-
# require_relative 'foo_addition'
|
|
560
|
-
# # This foo has the custom addition.
|
|
561
|
-
# foo1 = Foo.new(0, 1)
|
|
562
|
-
# json1 = JSON.generate(foo1)
|
|
563
|
-
# obj1 = JSON.parse(json1, create_additions: true)
|
|
564
|
-
# # Make a nice display.
|
|
565
|
-
# display = <<~EOT
|
|
566
|
-
# Generated JSON:
|
|
567
|
-
# Without custom addition: #{json0} (#{json0.class})
|
|
568
|
-
# With custom addition: #{json1} (#{json1.class})
|
|
569
|
-
# Parsed JSON:
|
|
570
|
-
# Without custom addition: #{obj0.inspect} (#{obj0.class})
|
|
571
|
-
# With custom addition: #{obj1.inspect} (#{obj1.class})
|
|
572
|
-
# EOT
|
|
573
|
-
# puts display
|
|
574
|
-
#
|
|
575
|
-
# Output:
|
|
576
|
-
#
|
|
577
|
-
# Generated JSON:
|
|
578
|
-
# Without custom addition: "#<Foo:0x0000000006534e80>" (String)
|
|
579
|
-
# With custom addition: {"json_class":"Foo","a":[0,1]} (String)
|
|
580
|
-
# Parsed JSON:
|
|
581
|
-
# Without custom addition: "#<Foo:0x0000000006534e80>" (String)
|
|
582
|
-
# With custom addition: #<Foo:0x0000000006473bb8 @bar=0, @baz=1> (Foo)
|
|
583
|
-
#
|
|
584
449
|
module JSON
|
|
585
450
|
require 'json/version'
|
|
586
451
|
require 'json/ext'
|
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:
|
|
4
|
+
version: 3.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Florian Frank
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
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
|
|
@@ -26,31 +26,19 @@ files:
|
|
|
26
26
|
- ext/json/ext/fbuffer/fbuffer.h
|
|
27
27
|
- ext/json/ext/generator/extconf.rb
|
|
28
28
|
- ext/json/ext/generator/generator.c
|
|
29
|
-
- ext/json/ext/
|
|
29
|
+
- ext/json/ext/json.h
|
|
30
30
|
- ext/json/ext/parser/extconf.rb
|
|
31
31
|
- ext/json/ext/parser/parser.c
|
|
32
|
+
- ext/json/ext/simd/conf.rb
|
|
33
|
+
- ext/json/ext/simd/simd.h
|
|
34
|
+
- ext/json/ext/vendor/fast_float_parser.h
|
|
32
35
|
- ext/json/ext/vendor/fpconv.c
|
|
33
36
|
- ext/json/ext/vendor/jeaiii-ltoa.h
|
|
34
37
|
- json.gemspec
|
|
35
38
|
- lib/json.rb
|
|
36
|
-
- lib/json/add/bigdecimal.rb
|
|
37
|
-
- lib/json/add/complex.rb
|
|
38
|
-
- lib/json/add/core.rb
|
|
39
|
-
- lib/json/add/date.rb
|
|
40
|
-
- lib/json/add/date_time.rb
|
|
41
|
-
- lib/json/add/exception.rb
|
|
42
|
-
- lib/json/add/ostruct.rb
|
|
43
|
-
- lib/json/add/range.rb
|
|
44
|
-
- lib/json/add/rational.rb
|
|
45
|
-
- lib/json/add/regexp.rb
|
|
46
|
-
- lib/json/add/set.rb
|
|
47
|
-
- lib/json/add/struct.rb
|
|
48
|
-
- lib/json/add/symbol.rb
|
|
49
|
-
- lib/json/add/time.rb
|
|
50
39
|
- lib/json/common.rb
|
|
51
40
|
- lib/json/ext.rb
|
|
52
41
|
- lib/json/ext/generator/state.rb
|
|
53
|
-
- lib/json/generic_object.rb
|
|
54
42
|
- lib/json/truffle_ruby/generator.rb
|
|
55
43
|
- lib/json/version.rb
|
|
56
44
|
homepage: https://github.com/ruby/json
|
|
@@ -80,7 +68,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
80
68
|
- !ruby/object:Gem::Version
|
|
81
69
|
version: '0'
|
|
82
70
|
requirements: []
|
|
83
|
-
rubygems_version:
|
|
71
|
+
rubygems_version: 4.0.16
|
|
84
72
|
specification_version: 4
|
|
85
73
|
summary: JSON Implementation for Ruby
|
|
86
74
|
test_files: []
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
typedef enum {
|
|
2
|
-
SIMD_NONE,
|
|
3
|
-
SIMD_NEON,
|
|
4
|
-
SIMD_SSE2
|
|
5
|
-
} SIMD_Implementation;
|
|
6
|
-
|
|
7
|
-
#ifdef JSON_ENABLE_SIMD
|
|
8
|
-
|
|
9
|
-
#ifdef __clang__
|
|
10
|
-
#if __has_builtin(__builtin_ctzll)
|
|
11
|
-
#define HAVE_BUILTIN_CTZLL 1
|
|
12
|
-
#else
|
|
13
|
-
#define HAVE_BUILTIN_CTZLL 0
|
|
14
|
-
#endif
|
|
15
|
-
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
|
|
16
|
-
#define HAVE_BUILTIN_CTZLL 1
|
|
17
|
-
#else
|
|
18
|
-
#define HAVE_BUILTIN_CTZLL 0
|
|
19
|
-
#endif
|
|
20
|
-
|
|
21
|
-
static inline uint32_t trailing_zeros64(uint64_t input) {
|
|
22
|
-
#if HAVE_BUILTIN_CTZLL
|
|
23
|
-
return __builtin_ctzll(input);
|
|
24
|
-
#else
|
|
25
|
-
uint32_t trailing_zeros = 0;
|
|
26
|
-
uint64_t temp = input;
|
|
27
|
-
while ((temp & 1) == 0 && temp > 0) {
|
|
28
|
-
trailing_zeros++;
|
|
29
|
-
temp >>= 1;
|
|
30
|
-
}
|
|
31
|
-
return trailing_zeros;
|
|
32
|
-
#endif
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
static inline int trailing_zeros(int input) {
|
|
36
|
-
#if HAVE_BUILTIN_CTZLL
|
|
37
|
-
return __builtin_ctz(input);
|
|
38
|
-
#else
|
|
39
|
-
int trailing_zeros = 0;
|
|
40
|
-
int temp = input;
|
|
41
|
-
while ((temp & 1) == 0 && temp > 0) {
|
|
42
|
-
trailing_zeros++;
|
|
43
|
-
temp >>= 1;
|
|
44
|
-
}
|
|
45
|
-
return trailing_zeros;
|
|
46
|
-
#endif
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
#define SIMD_MINIMUM_THRESHOLD 6
|
|
50
|
-
|
|
51
|
-
#if defined(__ARM_NEON) || defined(__ARM_NEON__) || defined(__aarch64__) || defined(_M_ARM64)
|
|
52
|
-
#include <arm_neon.h>
|
|
53
|
-
|
|
54
|
-
#define FIND_SIMD_IMPLEMENTATION_DEFINED 1
|
|
55
|
-
static SIMD_Implementation find_simd_implementation(void) {
|
|
56
|
-
return SIMD_NEON;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
#define HAVE_SIMD 1
|
|
60
|
-
#define HAVE_SIMD_NEON 1
|
|
61
|
-
|
|
62
|
-
uint8x16x4_t load_uint8x16_4(const unsigned char *table) {
|
|
63
|
-
uint8x16x4_t tab;
|
|
64
|
-
tab.val[0] = vld1q_u8(table);
|
|
65
|
-
tab.val[1] = vld1q_u8(table+16);
|
|
66
|
-
tab.val[2] = vld1q_u8(table+32);
|
|
67
|
-
tab.val[3] = vld1q_u8(table+48);
|
|
68
|
-
return tab;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
#endif /* ARM Neon Support.*/
|
|
72
|
-
|
|
73
|
-
#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)
|
|
74
|
-
|
|
75
|
-
#ifdef HAVE_X86INTRIN_H
|
|
76
|
-
#include <x86intrin.h>
|
|
77
|
-
|
|
78
|
-
#define HAVE_SIMD 1
|
|
79
|
-
#define HAVE_SIMD_SSE2 1
|
|
80
|
-
|
|
81
|
-
#ifdef HAVE_CPUID_H
|
|
82
|
-
#define FIND_SIMD_IMPLEMENTATION_DEFINED 1
|
|
83
|
-
|
|
84
|
-
#include <cpuid.h>
|
|
85
|
-
#endif /* HAVE_CPUID_H */
|
|
86
|
-
|
|
87
|
-
static SIMD_Implementation find_simd_implementation(void) {
|
|
88
|
-
|
|
89
|
-
#if defined(__GNUC__ ) || defined(__clang__)
|
|
90
|
-
#ifdef __GNUC__
|
|
91
|
-
__builtin_cpu_init();
|
|
92
|
-
#endif /* __GNUC__ */
|
|
93
|
-
|
|
94
|
-
// TODO Revisit. I think the SSE version now only uses SSE2 instructions.
|
|
95
|
-
if (__builtin_cpu_supports("sse2")) {
|
|
96
|
-
return SIMD_SSE2;
|
|
97
|
-
}
|
|
98
|
-
#endif /* __GNUC__ || __clang__*/
|
|
99
|
-
|
|
100
|
-
return SIMD_NONE;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
#endif /* HAVE_X86INTRIN_H */
|
|
104
|
-
#endif /* X86_64 Support */
|
|
105
|
-
|
|
106
|
-
#endif /* JSON_ENABLE_SIMD */
|
|
107
|
-
|
|
108
|
-
#ifndef FIND_SIMD_IMPLEMENTATION_DEFINED
|
|
109
|
-
static SIMD_Implementation find_simd_implementation(void) {
|
|
110
|
-
return SIMD_NONE;
|
|
111
|
-
}
|
|
112
|
-
#endif
|
data/lib/json/add/bigdecimal.rb
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
|
|
3
|
-
require 'json'
|
|
4
|
-
end
|
|
5
|
-
begin
|
|
6
|
-
require 'bigdecimal'
|
|
7
|
-
rescue LoadError
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
class BigDecimal
|
|
11
|
-
|
|
12
|
-
# See #as_json.
|
|
13
|
-
def self.json_create(object)
|
|
14
|
-
BigDecimal._load object['b']
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
# Methods <tt>BigDecimal#as_json</tt> and +BigDecimal.json_create+ may be used
|
|
18
|
-
# to serialize and deserialize a \BigDecimal object;
|
|
19
|
-
# see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
|
|
20
|
-
#
|
|
21
|
-
# \Method <tt>BigDecimal#as_json</tt> serializes +self+,
|
|
22
|
-
# returning a 2-element hash representing +self+:
|
|
23
|
-
#
|
|
24
|
-
# require 'json/add/bigdecimal'
|
|
25
|
-
# x = BigDecimal(2).as_json # => {"json_class"=>"BigDecimal", "b"=>"27:0.2e1"}
|
|
26
|
-
# y = BigDecimal(2.0, 4).as_json # => {"json_class"=>"BigDecimal", "b"=>"36:0.2e1"}
|
|
27
|
-
# z = BigDecimal(Complex(2, 0)).as_json # => {"json_class"=>"BigDecimal", "b"=>"27:0.2e1"}
|
|
28
|
-
#
|
|
29
|
-
# \Method +JSON.create+ deserializes such a hash, returning a \BigDecimal object:
|
|
30
|
-
#
|
|
31
|
-
# BigDecimal.json_create(x) # => 0.2e1
|
|
32
|
-
# BigDecimal.json_create(y) # => 0.2e1
|
|
33
|
-
# BigDecimal.json_create(z) # => 0.2e1
|
|
34
|
-
#
|
|
35
|
-
def as_json(*)
|
|
36
|
-
{
|
|
37
|
-
JSON.create_id => self.class.name,
|
|
38
|
-
'b' => _dump.force_encoding(Encoding::UTF_8),
|
|
39
|
-
}
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
# Returns a JSON string representing +self+:
|
|
43
|
-
#
|
|
44
|
-
# require 'json/add/bigdecimal'
|
|
45
|
-
# puts BigDecimal(2).to_json
|
|
46
|
-
# puts BigDecimal(2.0, 4).to_json
|
|
47
|
-
# puts BigDecimal(Complex(2, 0)).to_json
|
|
48
|
-
#
|
|
49
|
-
# Output:
|
|
50
|
-
#
|
|
51
|
-
# {"json_class":"BigDecimal","b":"27:0.2e1"}
|
|
52
|
-
# {"json_class":"BigDecimal","b":"36:0.2e1"}
|
|
53
|
-
# {"json_class":"BigDecimal","b":"27:0.2e1"}
|
|
54
|
-
#
|
|
55
|
-
def to_json(*args)
|
|
56
|
-
as_json.to_json(*args)
|
|
57
|
-
end
|
|
58
|
-
end if defined?(::BigDecimal)
|
data/lib/json/add/complex.rb
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
|
|
3
|
-
require 'json'
|
|
4
|
-
end
|
|
5
|
-
|
|
6
|
-
class Complex
|
|
7
|
-
|
|
8
|
-
# See #as_json.
|
|
9
|
-
def self.json_create(object)
|
|
10
|
-
Complex(object['r'], object['i'])
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
# Methods <tt>Complex#as_json</tt> and +Complex.json_create+ may be used
|
|
14
|
-
# to serialize and deserialize a \Complex object;
|
|
15
|
-
# see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
|
|
16
|
-
#
|
|
17
|
-
# \Method <tt>Complex#as_json</tt> serializes +self+,
|
|
18
|
-
# returning a 2-element hash representing +self+:
|
|
19
|
-
#
|
|
20
|
-
# require 'json/add/complex'
|
|
21
|
-
# x = Complex(2).as_json # => {"json_class"=>"Complex", "r"=>2, "i"=>0}
|
|
22
|
-
# y = Complex(2.0, 4).as_json # => {"json_class"=>"Complex", "r"=>2.0, "i"=>4}
|
|
23
|
-
#
|
|
24
|
-
# \Method +JSON.create+ deserializes such a hash, returning a \Complex object:
|
|
25
|
-
#
|
|
26
|
-
# Complex.json_create(x) # => (2+0i)
|
|
27
|
-
# Complex.json_create(y) # => (2.0+4i)
|
|
28
|
-
#
|
|
29
|
-
def as_json(*)
|
|
30
|
-
{
|
|
31
|
-
JSON.create_id => self.class.name,
|
|
32
|
-
'r' => real,
|
|
33
|
-
'i' => imag,
|
|
34
|
-
}
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# Returns a JSON string representing +self+:
|
|
38
|
-
#
|
|
39
|
-
# require 'json/add/complex'
|
|
40
|
-
# puts Complex(2).to_json
|
|
41
|
-
# puts Complex(2.0, 4).to_json
|
|
42
|
-
#
|
|
43
|
-
# Output:
|
|
44
|
-
#
|
|
45
|
-
# {"json_class":"Complex","r":2,"i":0}
|
|
46
|
-
# {"json_class":"Complex","r":2.0,"i":4}
|
|
47
|
-
#
|
|
48
|
-
def to_json(*args)
|
|
49
|
-
as_json.to_json(*args)
|
|
50
|
-
end
|
|
51
|
-
end
|