json-extended 2.20.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.
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JSON
4
+ VERSION = '2.20.0'
5
+ end
data/lib/json.rb ADDED
@@ -0,0 +1,689 @@
1
+ # frozen_string_literal: true
2
+ require 'json/common'
3
+
4
+ ##
5
+ # = JavaScript \Object Notation (\JSON)
6
+ #
7
+ # \JSON is a lightweight data-interchange format.
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
+ #
18
+ # A \JSON value is one of the following:
19
+ # - Double-quoted text: <tt>"foo"</tt>.
20
+ # - Number: +1+, +1.0+, +2.0e2+.
21
+ # - Boolean: +true+, +false+.
22
+ # - Null: +null+.
23
+ # - \Array: an ordered list of values, enclosed by square brackets:
24
+ # ["foo", 1, 1.0, 2.0e2, true, false, null]
25
+ #
26
+ # - \Object: a collection of name/value pairs, enclosed by curly braces;
27
+ # each name is double-quoted text;
28
+ # the values may be any \JSON values:
29
+ # {"a": "foo", "b": 1, "c": 1.0, "d": 2.0e2, "e": true, "f": false, "g": null}
30
+ #
31
+ # A \JSON array or object may contain nested arrays, objects, and scalars
32
+ # to any depth:
33
+ # {"foo": {"bar": 1, "baz": 2}, "bat": [0, 1, 2]}
34
+ # [{"foo": 0, "bar": 1}, ["baz", 2]]
35
+ #
36
+ # == Using \Module \JSON
37
+ #
38
+ # To make module \JSON available in your code, begin with:
39
+ # require 'json'
40
+ #
41
+ # All examples here assume that this has been done.
42
+ #
43
+ # === Parsing \JSON
44
+ #
45
+ # You can parse a \String containing \JSON data using
46
+ # either of two methods:
47
+ # - <tt>JSON.parse(source, opts)</tt>
48
+ # - <tt>JSON.parse!(source, opts)</tt>
49
+ #
50
+ # where
51
+ # - +source+ is a Ruby object.
52
+ # - +opts+ is a \Hash object containing options
53
+ # that control both input allowed and output formatting.
54
+ #
55
+ # The difference between the two methods
56
+ # is that JSON.parse! omits some checks
57
+ # and may not be safe for some +source+ data;
58
+ # use it only for data from trusted sources.
59
+ # Use the safer method JSON.parse for less trusted sources.
60
+ #
61
+ # ==== Parsing \JSON Arrays
62
+ #
63
+ # When +source+ is a \JSON array, JSON.parse by default returns a Ruby \Array:
64
+ # json = '["foo", 1, 1.0, 2.0e2, true, false, null]'
65
+ # ruby = JSON.parse(json)
66
+ # ruby # => ["foo", 1, 1.0, 200.0, true, false, nil]
67
+ # ruby.class # => Array
68
+ #
69
+ # The \JSON array may contain nested arrays, objects, and scalars
70
+ # to any depth:
71
+ # json = '[{"foo": 0, "bar": 1}, ["baz", 2]]'
72
+ # JSON.parse(json) # => [{"foo"=>0, "bar"=>1}, ["baz", 2]]
73
+ #
74
+ # ==== Parsing \JSON \Objects
75
+ #
76
+ # When the source is a \JSON object, JSON.parse by default returns a Ruby \Hash:
77
+ # json = '{"a": "foo", "b": 1, "c": 1.0, "d": 2.0e2, "e": true, "f": false, "g": null}'
78
+ # ruby = JSON.parse(json)
79
+ # ruby # => {"a"=>"foo", "b"=>1, "c"=>1.0, "d"=>200.0, "e"=>true, "f"=>false, "g"=>nil}
80
+ # ruby.class # => Hash
81
+ #
82
+ # The \JSON object may contain nested arrays, objects, and scalars
83
+ # to any depth:
84
+ # json = '{"foo": {"bar": 1, "baz": 2}, "bat": [0, 1, 2]}'
85
+ # JSON.parse(json) # => {"foo"=>{"bar"=>1, "baz"=>2}, "bat"=>[0, 1, 2]}
86
+ #
87
+ # ==== Parsing \JSON Scalars
88
+ #
89
+ # When the source is a \JSON scalar (not an array or object),
90
+ # JSON.parse returns a Ruby scalar.
91
+ #
92
+ # \String:
93
+ # ruby = JSON.parse('"foo"')
94
+ # ruby # => 'foo'
95
+ # ruby.class # => String
96
+ # \Integer:
97
+ # ruby = JSON.parse('1')
98
+ # ruby # => 1
99
+ # ruby.class # => Integer
100
+ # \Float:
101
+ # ruby = JSON.parse('1.0')
102
+ # ruby # => 1.0
103
+ # ruby.class # => Float
104
+ # ruby = JSON.parse('2.0e2')
105
+ # ruby # => 200
106
+ # ruby.class # => Float
107
+ # Boolean:
108
+ # ruby = JSON.parse('true')
109
+ # ruby # => true
110
+ # ruby.class # => TrueClass
111
+ # ruby = JSON.parse('false')
112
+ # ruby # => false
113
+ # ruby.class # => FalseClass
114
+ # Null:
115
+ # ruby = JSON.parse('null')
116
+ # ruby # => nil
117
+ # ruby.class # => NilClass
118
+ #
119
+ # ==== Parsing Options
120
+ #
121
+ # ====== Input Options
122
+ #
123
+ # Option +max_nesting+ (\Integer) specifies the maximum nesting depth allowed;
124
+ # defaults to +100+; specify +false+ to disable depth checking.
125
+ #
126
+ # With the default, +false+:
127
+ # source = '[0, [1, [2, [3]]]]'
128
+ # ruby = JSON.parse(source)
129
+ # ruby # => [0, [1, [2, [3]]]]
130
+ # Too deep:
131
+ # # Raises JSON::NestingError (nesting of 2 is too deep):
132
+ # JSON.parse(source, {max_nesting: 1})
133
+ # Bad value:
134
+ # # Raises TypeError (wrong argument type Symbol (expected Fixnum)):
135
+ # JSON.parse(source, {max_nesting: :foo})
136
+ #
137
+ # ---
138
+ #
139
+ # Option +allow_duplicate_key+ specifies whether duplicate keys in objects
140
+ # should be ignored or cause an error to be raised:
141
+ #
142
+ # When not specified:
143
+ # # The last value is used and a deprecation warning emitted.
144
+ # JSON.parse('{"a": 1, "a":2}') => {"a" => 2}
145
+ # # warning: detected duplicate keys in JSON object.
146
+ # # This will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`
147
+ #
148
+ # When set to +true+:
149
+ # # The last value is used.
150
+ # JSON.parse('{"a": 1, "a":2}') => {"a" => 2}
151
+ #
152
+ # When set to +false+, the future default:
153
+ # JSON.parse('{"a": 1, "a":2}') => duplicate key at line 1 column 1 (JSON::ParserError)
154
+ #
155
+ # ---
156
+ #
157
+ # Option +allow_nan+ (boolean) specifies whether to allow
158
+ # NaN, Infinity, and MinusInfinity in +source+;
159
+ # defaults to +false+.
160
+ #
161
+ # With the default, +false+:
162
+ # # Raises JSON::ParserError (225: unexpected token at '[NaN]'):
163
+ # JSON.parse('[NaN]')
164
+ # # Raises JSON::ParserError (232: unexpected token at '[Infinity]'):
165
+ # JSON.parse('[Infinity]')
166
+ # # Raises JSON::ParserError (248: unexpected token at '[-Infinity]'):
167
+ # JSON.parse('[-Infinity]')
168
+ # Allow:
169
+ # source = '[NaN, Infinity, -Infinity]'
170
+ # ruby = JSON.parse(source, {allow_nan: true})
171
+ # ruby # => [NaN, Infinity, -Infinity]
172
+ #
173
+ # ---
174
+ #
175
+ # Option +allow_trailing_comma+ (boolean) specifies whether to allow
176
+ # trailing commas in objects and arrays;
177
+ # defaults to +false+.
178
+ #
179
+ # With the default, +false+:
180
+ # JSON.parse('[1,]') # unexpected character: ']' at line 1 column 4 (JSON::ParserError)
181
+ #
182
+ # When enabled:
183
+ # JSON.parse('[1,]', allow_trailing_comma: true) # => [1]
184
+ #
185
+ # ---
186
+ #
187
+ # Option +allow_comments+ (boolean) specifies whether to allow
188
+ # JavaScript style comments (either <tt>// comment</tt> or <tt>/* comment */</tt>);
189
+ # defaults to +false+.
190
+ #
191
+ # When not specified, a deprecation warning is emitted if a comment is encountered.
192
+ #
193
+ # When set to +true+, comments are ignored:
194
+ # JSON.parse('/* comment */ {"a": 1, "a":2}') # => {"a" => 2}
195
+ #
196
+ # When set to +false+, the future default:
197
+ # JSON.parse('/* comment */ {"a": 1, "a":2}') # unexpected character: '/' at line 1 column 1 (JSON::ParserError)
198
+ #
199
+ # ---
200
+ #
201
+ # Option +allow_control_characters+ (boolean) specifies whether to allow
202
+ # unescaped ASCII control characters, such as newlines, in strings;
203
+ # defaults to +false+.
204
+ #
205
+ # With the default, +false+:
206
+ # JSON.parse(%{"Hello\nWorld"}) # invalid ASCII control character in string (JSON::ParserError)
207
+ #
208
+ # When enabled:
209
+ # JSON.parse(%{"Hello\nWorld"}, allow_control_characters: true) # => "Hello\nWorld"
210
+ #
211
+ # ---
212
+ #
213
+ # Option +allow_invalid_escape+ (boolean) specifies whether to ignore backslahes that are followed
214
+ # by an invalid escape character in strings;
215
+ # defaults to +false+.
216
+ #
217
+ # With the default, +false+:
218
+ # JSON.parse('"Hell\o"') # invalid escape character in string (JSON::ParserError)
219
+ #
220
+ # When enabled:
221
+ # JSON.parse('"Hell\o"', allow_invalid_escape: true) # => "Hello"
222
+ #
223
+ # ====== Output Options
224
+ #
225
+ # Option +freeze+ (boolean) specifies whether the returned objects will be frozen;
226
+ # defaults to +false+.
227
+ #
228
+ # Option +symbolize_names+ (boolean) specifies whether returned \Hash keys
229
+ # should be Symbols;
230
+ # defaults to +false+ (use Strings).
231
+ #
232
+ # With the default, +false+:
233
+ # source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}'
234
+ # ruby = JSON.parse(source)
235
+ # ruby # => {"a"=>"foo", "b"=>1.0, "c"=>true, "d"=>false, "e"=>nil}
236
+ # Use Symbols:
237
+ # ruby = JSON.parse(source, {symbolize_names: true})
238
+ # ruby # => {:a=>"foo", :b=>1.0, :c=>true, :d=>false, :e=>nil}
239
+ #
240
+ # ---
241
+ #
242
+ # Option +object_class+ (\Class) specifies the Ruby class to be used
243
+ # for each \JSON object;
244
+ # defaults to \Hash.
245
+ #
246
+ # With the default, \Hash:
247
+ # source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}'
248
+ # ruby = JSON.parse(source)
249
+ # ruby.class # => Hash
250
+ # Use class \OpenStruct:
251
+ # ruby = JSON.parse(source, {object_class: OpenStruct})
252
+ # ruby # => #<OpenStruct a="foo", b=1.0, c=true, d=false, e=nil>
253
+ #
254
+ # ---
255
+ #
256
+ # Option +array_class+ (\Class) specifies the Ruby class to be used
257
+ # for each \JSON array;
258
+ # defaults to \Array.
259
+ #
260
+ # With the default, \Array:
261
+ # source = '["foo", 1.0, true, false, null]'
262
+ # ruby = JSON.parse(source)
263
+ # ruby.class # => Array
264
+ # Use class \Set:
265
+ # ruby = JSON.parse(source, {array_class: Set})
266
+ # ruby # => #<Set: {"foo", 1.0, true, false, nil}>
267
+ #
268
+ # ---
269
+ #
270
+ # Option +create_additions+ (boolean) specifies whether to use \JSON additions in parsing.
271
+ # See {\JSON Additions}[#module-JSON-label-JSON+Additions].
272
+ #
273
+ # === Generating \JSON
274
+ #
275
+ # To generate a Ruby \String containing \JSON data,
276
+ # use method <tt>JSON.generate(source, opts)</tt>, where
277
+ # - +source+ is a Ruby object.
278
+ # - +opts+ is a \Hash object containing options
279
+ # that control both input allowed and output formatting.
280
+ #
281
+ # ==== Generating \JSON from Arrays
282
+ #
283
+ # When the source is a Ruby \Array, JSON.generate returns
284
+ # a \String containing a \JSON array:
285
+ # ruby = [0, 's', :foo]
286
+ # json = JSON.generate(ruby)
287
+ # json # => '[0,"s","foo"]'
288
+ #
289
+ # The Ruby \Array array may contain nested arrays, hashes, and scalars
290
+ # to any depth:
291
+ # ruby = [0, [1, 2], {foo: 3, bar: 4}]
292
+ # json = JSON.generate(ruby)
293
+ # json # => '[0,[1,2],{"foo":3,"bar":4}]'
294
+ #
295
+ # ==== Generating \JSON from Hashes
296
+ #
297
+ # When the source is a Ruby \Hash, JSON.generate returns
298
+ # a \String containing a \JSON object:
299
+ # ruby = {foo: 0, bar: 's', baz: :bat}
300
+ # json = JSON.generate(ruby)
301
+ # json # => '{"foo":0,"bar":"s","baz":"bat"}'
302
+ #
303
+ # The Ruby \Hash array may contain nested arrays, hashes, and scalars
304
+ # to any depth:
305
+ # ruby = {foo: [0, 1], bar: {baz: 2, bat: 3}, bam: :bad}
306
+ # json = JSON.generate(ruby)
307
+ # json # => '{"foo":[0,1],"bar":{"baz":2,"bat":3},"bam":"bad"}'
308
+ #
309
+ # ==== Generating \JSON from Other Objects
310
+ #
311
+ # When the source is neither an \Array nor a \Hash,
312
+ # the generated \JSON data depends on the class of the source.
313
+ #
314
+ # When the source is a Ruby \Integer or \Float, JSON.generate returns
315
+ # a \String containing a \JSON number:
316
+ # JSON.generate(42) # => '42'
317
+ # JSON.generate(0.42) # => '0.42'
318
+ #
319
+ # When the source is a Ruby \String, JSON.generate returns
320
+ # a \String containing a \JSON string (with double-quotes):
321
+ # JSON.generate('A string') # => '"A string"'
322
+ #
323
+ # When the source is +true+, +false+ or +nil+, JSON.generate returns
324
+ # a \String containing the corresponding \JSON token:
325
+ # JSON.generate(true) # => 'true'
326
+ # JSON.generate(false) # => 'false'
327
+ # JSON.generate(nil) # => 'null'
328
+ #
329
+ # When the source is none of the above, JSON.generate returns
330
+ # a \String containing a \JSON string representation of the source:
331
+ # JSON.generate(:foo) # => '"foo"'
332
+ # JSON.generate(Complex(0, 0)) # => '"0+0i"'
333
+ # JSON.generate(Dir.new('.')) # => '"#<Dir>"'
334
+ #
335
+ # ==== Generating Options
336
+ #
337
+ # ====== Input Options
338
+ #
339
+ # Option +allow_nan+ (boolean) specifies whether
340
+ # +NaN+, +Infinity+, and <tt>-Infinity</tt> may be generated;
341
+ # defaults to +false+.
342
+ #
343
+ # With the default, +false+:
344
+ # # Raises JSON::GeneratorError (920: NaN not allowed in JSON):
345
+ # JSON.generate(JSON::NaN)
346
+ # # Raises JSON::GeneratorError (917: Infinity not allowed in JSON):
347
+ # JSON.generate(JSON::Infinity)
348
+ # # Raises JSON::GeneratorError (917: -Infinity not allowed in JSON):
349
+ # JSON.generate(JSON::MinusInfinity)
350
+ #
351
+ # Allow:
352
+ # ruby = [Float::NAN, Float::INFINITY, JSON::NaN, JSON::Infinity, JSON::MinusInfinity]
353
+ # JSON.generate(ruby, allow_nan: true) # => '[NaN,Infinity,NaN,Infinity,-Infinity]'
354
+ #
355
+ # ---
356
+ #
357
+ # Option +allow_duplicate_key+ (boolean) specifies whether
358
+ # hashes with duplicate keys should be allowed or produce an error.
359
+ # defaults to emit a deprecation warning.
360
+ #
361
+ # With the default, (not set):
362
+ # Warning[:deprecated] = true
363
+ # JSON.generate({ foo: 1, "foo" => 2 })
364
+ # # warning: detected duplicate key "foo" in {foo: 1, "foo" => 2}.
365
+ # # This will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`
366
+ # # => '{"foo":1,"foo":2}'
367
+ #
368
+ # With <tt>false</tt>
369
+ # JSON.generate({ foo: 1, "foo" => 2 }, allow_duplicate_key: false)
370
+ # # detected duplicate key "foo" in {foo: 1, "foo" => 2} (JSON::GeneratorError)
371
+ #
372
+ # In version 3.0, <tt>false</tt> will become the default.
373
+ #
374
+ # ---
375
+ #
376
+ # Option +max_nesting+ (\Integer) specifies the maximum nesting depth
377
+ # in +obj+; defaults to +100+.
378
+ #
379
+ # With the default, +100+:
380
+ # obj = [[[[[[0]]]]]]
381
+ # JSON.generate(obj) # => '[[[[[[0]]]]]]'
382
+ #
383
+ # Too deep:
384
+ # # Raises JSON::NestingError (nesting of 2 is too deep):
385
+ # JSON.generate(obj, max_nesting: 2)
386
+ #
387
+ # ====== Escaping Options
388
+ #
389
+ # Options +script_safe+ (boolean) specifies wether <tt>'\u2028'</tt>, <tt>'\u2029'</tt>
390
+ # and <tt>'/'</tt> should be escaped as to make the JSON object safe to interpolate in script
391
+ # tags.
392
+ #
393
+ # Options +ascii_only+ (boolean) specifies wether all characters outside the ASCII range
394
+ # should be escaped.
395
+ #
396
+ # ====== Output Options
397
+ #
398
+ # The default formatting options generate the most compact
399
+ # \JSON data, all on one line and with no whitespace.
400
+ #
401
+ # You can use these formatting options to generate
402
+ # \JSON data in a more open format, using whitespace.
403
+ # See also JSON.pretty_generate.
404
+ #
405
+ # - Option +array_nl+ (\String) specifies a string (usually a newline)
406
+ # to be inserted after each \JSON array; defaults to the empty \String, <tt>''</tt>.
407
+ # - Option +object_nl+ (\String) specifies a string (usually a newline)
408
+ # to be inserted after each \JSON object; defaults to the empty \String, <tt>''</tt>.
409
+ # - Option +indent+ (\String) specifies the string (usually spaces) to be
410
+ # used for indentation; defaults to the empty \String, <tt>''</tt>;
411
+ # defaults to the empty \String, <tt>''</tt>;
412
+ # has no effect unless options +array_nl+ or +object_nl+ specify newlines.
413
+ # - Option +space+ (\String) specifies a string (usually a space) to be
414
+ # inserted after the colon in each \JSON object's pair;
415
+ # defaults to the empty \String, <tt>''</tt>.
416
+ # - Option +space_before+ (\String) specifies a string (usually a space) to be
417
+ # inserted before the colon in each \JSON object's pair;
418
+ # defaults to the empty \String, <tt>''</tt>.
419
+ #
420
+ # In this example, +obj+ is used first to generate the shortest
421
+ # \JSON data (no whitespace), then again with all formatting options
422
+ # specified:
423
+ #
424
+ # obj = {foo: [:bar, :baz], bat: {bam: 0, bad: 1}}
425
+ # json = JSON.generate(obj)
426
+ # puts 'Compact:', json
427
+ # opts = {
428
+ # array_nl: "\n",
429
+ # object_nl: "\n",
430
+ # indent: ' ',
431
+ # space_before: ' ',
432
+ # space: ' '
433
+ # }
434
+ # puts 'Open:', JSON.generate(obj, opts)
435
+ #
436
+ # Output:
437
+ # Compact:
438
+ # {"foo":["bar","baz"],"bat":{"bam":0,"bad":1}}
439
+ # Open:
440
+ # {
441
+ # "foo" : [
442
+ # "bar",
443
+ # "baz"
444
+ # ],
445
+ # "bat" : {
446
+ # "bam" : 0,
447
+ # "bad" : 1
448
+ # }
449
+ # }
450
+ #
451
+ # == \JSON Additions
452
+ #
453
+ # Note that JSON Additions must only be used with trusted data, and is
454
+ # deprecated.
455
+ #
456
+ # When you "round trip" a non-\String object from Ruby to \JSON and back,
457
+ # you have a new \String, instead of the object you began with:
458
+ # ruby0 = Range.new(0, 2)
459
+ # json = JSON.generate(ruby0)
460
+ # json # => '0..2"'
461
+ # ruby1 = JSON.parse(json)
462
+ # ruby1 # => '0..2'
463
+ # ruby1.class # => String
464
+ #
465
+ # You can use \JSON _additions_ to preserve the original object.
466
+ # The addition is an extension of a ruby class, so that:
467
+ # - \JSON.generate stores more information in the \JSON string.
468
+ # - \JSON.parse, called with option +create_additions+,
469
+ # uses that information to create a proper Ruby object.
470
+ #
471
+ # This example shows a \Range being generated into \JSON
472
+ # and parsed back into Ruby, both without and with
473
+ # the addition for \Range:
474
+ # ruby = Range.new(0, 2)
475
+ # # This passage does not use the addition for Range.
476
+ # json0 = JSON.generate(ruby)
477
+ # ruby0 = JSON.parse(json0)
478
+ # # This passage uses the addition for Range.
479
+ # require 'json/add/range'
480
+ # json1 = JSON.generate(ruby)
481
+ # ruby1 = JSON.parse(json1, create_additions: true)
482
+ # # Make a nice display.
483
+ # display = <<~EOT
484
+ # Generated JSON:
485
+ # Without addition: #{json0} (#{json0.class})
486
+ # With addition: #{json1} (#{json1.class})
487
+ # Parsed JSON:
488
+ # Without addition: #{ruby0.inspect} (#{ruby0.class})
489
+ # With addition: #{ruby1.inspect} (#{ruby1.class})
490
+ # EOT
491
+ # puts display
492
+ #
493
+ # This output shows the different results:
494
+ # Generated JSON:
495
+ # Without addition: "0..2" (String)
496
+ # With addition: {"json_class":"Range","a":[0,2,false]} (String)
497
+ # Parsed JSON:
498
+ # Without addition: "0..2" (String)
499
+ # With addition: 0..2 (Range)
500
+ #
501
+ # The \JSON module includes additions for certain classes.
502
+ # You can also craft custom additions.
503
+ # See {Custom \JSON Additions}[#module-JSON-label-Custom+JSON+Additions].
504
+ #
505
+ # === Built-in Additions
506
+ #
507
+ # The \JSON module includes additions for certain classes.
508
+ # To use an addition, +require+ its source:
509
+ # - BigDecimal: <tt>require 'json/add/bigdecimal'</tt>
510
+ # - Complex: <tt>require 'json/add/complex'</tt>
511
+ # - Date: <tt>require 'json/add/date'</tt>
512
+ # - DateTime: <tt>require 'json/add/date_time'</tt>
513
+ # - Exception: <tt>require 'json/add/exception'</tt>
514
+ # - OpenStruct: <tt>require 'json/add/ostruct'</tt>
515
+ # - Range: <tt>require 'json/add/range'</tt>
516
+ # - Rational: <tt>require 'json/add/rational'</tt>
517
+ # - Regexp: <tt>require 'json/add/regexp'</tt>
518
+ # - Set: <tt>require 'json/add/set'</tt>
519
+ # - Struct: <tt>require 'json/add/struct'</tt>
520
+ # - Symbol: <tt>require 'json/add/symbol'</tt>
521
+ # - Time: <tt>require 'json/add/time'</tt>
522
+ #
523
+ # To reduce punctuation clutter, the examples below
524
+ # show the generated \JSON via +puts+, rather than the usual +inspect+,
525
+ #
526
+ # \BigDecimal:
527
+ # require 'json/add/bigdecimal'
528
+ # ruby0 = BigDecimal(0) # 0.0
529
+ # json = JSON.generate(ruby0) # {"json_class":"BigDecimal","b":"27:0.0"}
530
+ # ruby1 = JSON.parse(json, create_additions: true) # 0.0
531
+ # ruby1.class # => BigDecimal
532
+ #
533
+ # \Complex:
534
+ # require 'json/add/complex'
535
+ # ruby0 = Complex(1+0i) # 1+0i
536
+ # json = JSON.generate(ruby0) # {"json_class":"Complex","r":1,"i":0}
537
+ # ruby1 = JSON.parse(json, create_additions: true) # 1+0i
538
+ # ruby1.class # Complex
539
+ #
540
+ # \Date:
541
+ # require 'json/add/date'
542
+ # ruby0 = Date.today # 2020-05-02
543
+ # json = JSON.generate(ruby0) # {"json_class":"Date","y":2020,"m":5,"d":2,"sg":2299161.0}
544
+ # ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02
545
+ # ruby1.class # Date
546
+ #
547
+ # \DateTime:
548
+ # require 'json/add/date_time'
549
+ # ruby0 = DateTime.now # 2020-05-02T10:38:13-05:00
550
+ # 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}
551
+ # ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02T10:38:13-05:00
552
+ # ruby1.class # DateTime
553
+ #
554
+ # \Exception (and its subclasses including \RuntimeError):
555
+ # require 'json/add/exception'
556
+ # ruby0 = Exception.new('A message') # A message
557
+ # json = JSON.generate(ruby0) # {"json_class":"Exception","m":"A message","b":null}
558
+ # ruby1 = JSON.parse(json, create_additions: true) # A message
559
+ # ruby1.class # Exception
560
+ # ruby0 = RuntimeError.new('Another message') # Another message
561
+ # json = JSON.generate(ruby0) # {"json_class":"RuntimeError","m":"Another message","b":null}
562
+ # ruby1 = JSON.parse(json, create_additions: true) # Another message
563
+ # ruby1.class # RuntimeError
564
+ #
565
+ # \OpenStruct:
566
+ # require 'json/add/ostruct'
567
+ # ruby0 = OpenStruct.new(name: 'Matz', language: 'Ruby') # #<OpenStruct name="Matz", language="Ruby">
568
+ # json = JSON.generate(ruby0) # {"json_class":"OpenStruct","t":{"name":"Matz","language":"Ruby"}}
569
+ # ruby1 = JSON.parse(json, create_additions: true) # #<OpenStruct name="Matz", language="Ruby">
570
+ # ruby1.class # OpenStruct
571
+ #
572
+ # \Range:
573
+ # require 'json/add/range'
574
+ # ruby0 = Range.new(0, 2) # 0..2
575
+ # json = JSON.generate(ruby0) # {"json_class":"Range","a":[0,2,false]}
576
+ # ruby1 = JSON.parse(json, create_additions: true) # 0..2
577
+ # ruby1.class # Range
578
+ #
579
+ # \Rational:
580
+ # require 'json/add/rational'
581
+ # ruby0 = Rational(1, 3) # 1/3
582
+ # json = JSON.generate(ruby0) # {"json_class":"Rational","n":1,"d":3}
583
+ # ruby1 = JSON.parse(json, create_additions: true) # 1/3
584
+ # ruby1.class # Rational
585
+ #
586
+ # \Regexp:
587
+ # require 'json/add/regexp'
588
+ # ruby0 = Regexp.new('foo') # (?-mix:foo)
589
+ # json = JSON.generate(ruby0) # {"json_class":"Regexp","o":0,"s":"foo"}
590
+ # ruby1 = JSON.parse(json, create_additions: true) # (?-mix:foo)
591
+ # ruby1.class # Regexp
592
+ #
593
+ # \Set:
594
+ # require 'json/add/set'
595
+ # ruby0 = Set.new([0, 1, 2]) # #<Set: {0, 1, 2}>
596
+ # json = JSON.generate(ruby0) # {"json_class":"Set","a":[0,1,2]}
597
+ # ruby1 = JSON.parse(json, create_additions: true) # #<Set: {0, 1, 2}>
598
+ # ruby1.class # Set
599
+ #
600
+ # \Struct:
601
+ # require 'json/add/struct'
602
+ # Customer = Struct.new(:name, :address) # Customer
603
+ # ruby0 = Customer.new("Dave", "123 Main") # #<struct Customer name="Dave", address="123 Main">
604
+ # json = JSON.generate(ruby0) # {"json_class":"Customer","v":["Dave","123 Main"]}
605
+ # ruby1 = JSON.parse(json, create_additions: true) # #<struct Customer name="Dave", address="123 Main">
606
+ # ruby1.class # Customer
607
+ #
608
+ # \Symbol:
609
+ # require 'json/add/symbol'
610
+ # ruby0 = :foo # foo
611
+ # json = JSON.generate(ruby0) # {"json_class":"Symbol","s":"foo"}
612
+ # ruby1 = JSON.parse(json, create_additions: true) # foo
613
+ # ruby1.class # Symbol
614
+ #
615
+ # \Time:
616
+ # require 'json/add/time'
617
+ # ruby0 = Time.now # 2020-05-02 11:28:26 -0500
618
+ # json = JSON.generate(ruby0) # {"json_class":"Time","s":1588436906,"n":840560000}
619
+ # ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02 11:28:26 -0500
620
+ # ruby1.class # Time
621
+ #
622
+ #
623
+ # === Custom \JSON Additions
624
+ #
625
+ # In addition to the \JSON additions provided,
626
+ # you can craft \JSON additions of your own,
627
+ # either for Ruby built-in classes or for user-defined classes.
628
+ #
629
+ # Here's a user-defined class +Foo+:
630
+ # class Foo
631
+ # attr_accessor :bar, :baz
632
+ # def initialize(bar, baz)
633
+ # self.bar = bar
634
+ # self.baz = baz
635
+ # end
636
+ # end
637
+ #
638
+ # Here's the \JSON addition for it:
639
+ # # Extend class Foo with JSON addition.
640
+ # class Foo
641
+ # # Serialize Foo object with its class name and arguments
642
+ # def to_json(*args)
643
+ # {
644
+ # JSON.create_id => self.class.name,
645
+ # 'a' => [ bar, baz ]
646
+ # }.to_json(*args)
647
+ # end
648
+ # # Deserialize JSON string by constructing new Foo object with arguments.
649
+ # def self.json_create(object)
650
+ # new(*object['a'])
651
+ # end
652
+ # end
653
+ #
654
+ # Demonstration:
655
+ # require 'json'
656
+ # # This Foo object has no custom addition.
657
+ # foo0 = Foo.new(0, 1)
658
+ # json0 = JSON.generate(foo0)
659
+ # obj0 = JSON.parse(json0)
660
+ # # Lood the custom addition.
661
+ # require_relative 'foo_addition'
662
+ # # This foo has the custom addition.
663
+ # foo1 = Foo.new(0, 1)
664
+ # json1 = JSON.generate(foo1)
665
+ # obj1 = JSON.parse(json1, create_additions: true)
666
+ # # Make a nice display.
667
+ # display = <<~EOT
668
+ # Generated JSON:
669
+ # Without custom addition: #{json0} (#{json0.class})
670
+ # With custom addition: #{json1} (#{json1.class})
671
+ # Parsed JSON:
672
+ # Without custom addition: #{obj0.inspect} (#{obj0.class})
673
+ # With custom addition: #{obj1.inspect} (#{obj1.class})
674
+ # EOT
675
+ # puts display
676
+ #
677
+ # Output:
678
+ #
679
+ # Generated JSON:
680
+ # Without custom addition: "#<Foo:0x0000000006534e80>" (String)
681
+ # With custom addition: {"json_class":"Foo","a":[0,1]} (String)
682
+ # Parsed JSON:
683
+ # Without custom addition: "#<Foo:0x0000000006534e80>" (String)
684
+ # With custom addition: #<Foo:0x0000000006473bb8 @bar=0, @baz=1> (Foo)
685
+ #
686
+ module JSON
687
+ require 'json/version'
688
+ require 'json/ext'
689
+ end