json 1.2.0 → 2.19.8

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.
Files changed (145) hide show
  1. checksums.yaml +7 -0
  2. data/BSDL +22 -0
  3. data/CHANGES.md +783 -0
  4. data/COPYING +14 -16
  5. data/LEGAL +20 -0
  6. data/README.md +310 -0
  7. data/ext/json/ext/fbuffer/fbuffer.h +260 -0
  8. data/ext/json/ext/generator/extconf.rb +15 -8
  9. data/ext/json/ext/generator/generator.c +1675 -613
  10. data/ext/json/ext/json.h +116 -0
  11. data/ext/json/ext/parser/extconf.rb +16 -7
  12. data/ext/json/ext/parser/parser.c +1649 -1772
  13. data/ext/json/ext/simd/conf.rb +24 -0
  14. data/ext/json/ext/simd/simd.h +208 -0
  15. data/ext/json/ext/vendor/fpconv.c +480 -0
  16. data/ext/json/ext/vendor/jeaiii-ltoa.h +267 -0
  17. data/ext/json/ext/vendor/ryu.h +819 -0
  18. data/json.gemspec +62 -0
  19. data/lib/json/add/bigdecimal.rb +58 -0
  20. data/lib/json/add/complex.rb +51 -0
  21. data/lib/json/add/core.rb +11 -133
  22. data/lib/json/add/date.rb +54 -0
  23. data/lib/json/add/date_time.rb +67 -0
  24. data/lib/json/add/exception.rb +49 -0
  25. data/lib/json/add/ostruct.rb +54 -0
  26. data/lib/json/add/range.rb +54 -0
  27. data/lib/json/add/rational.rb +49 -0
  28. data/lib/json/add/regexp.rb +48 -0
  29. data/lib/json/add/set.rb +48 -0
  30. data/lib/json/add/string.rb +35 -0
  31. data/lib/json/add/struct.rb +52 -0
  32. data/lib/json/add/symbol.rb +52 -0
  33. data/lib/json/add/time.rb +52 -0
  34. data/lib/json/common.rb +1056 -254
  35. data/lib/json/ext/generator/state.rb +103 -0
  36. data/lib/json/ext.rb +35 -5
  37. data/lib/json/generic_object.rb +67 -0
  38. data/lib/json/truffle_ruby/generator.rb +755 -0
  39. data/lib/json/version.rb +3 -6
  40. data/lib/json.rb +671 -6
  41. metadata +68 -159
  42. data/CHANGES +0 -136
  43. data/GPL +0 -340
  44. data/README +0 -360
  45. data/Rakefile +0 -287
  46. data/TODO +0 -1
  47. data/VERSION +0 -1
  48. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkComparison.log +0 -52
  49. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast-autocorrelation.dat +0 -1000
  50. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast.dat +0 -1001
  51. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty-autocorrelation.dat +0 -900
  52. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty.dat +0 -901
  53. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe-autocorrelation.dat +0 -1000
  54. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe.dat +0 -1001
  55. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt.log +0 -261
  56. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast-autocorrelation.dat +0 -1000
  57. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast.dat +0 -1001
  58. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty-autocorrelation.dat +0 -1000
  59. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty.dat +0 -1001
  60. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe-autocorrelation.dat +0 -1000
  61. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe.dat +0 -1001
  62. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure.log +0 -262
  63. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator-autocorrelation.dat +0 -1000
  64. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator.dat +0 -1001
  65. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails.log +0 -82
  66. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkComparison.log +0 -34
  67. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser-autocorrelation.dat +0 -900
  68. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser.dat +0 -901
  69. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt.log +0 -81
  70. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser-autocorrelation.dat +0 -1000
  71. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser.dat +0 -1001
  72. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure.log +0 -82
  73. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser-autocorrelation.dat +0 -1000
  74. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser.dat +0 -1001
  75. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails.log +0 -82
  76. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser-autocorrelation.dat +0 -1000
  77. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser.dat +0 -1001
  78. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML.log +0 -82
  79. data/benchmarks/generator_benchmark.rb +0 -165
  80. data/benchmarks/parser_benchmark.rb +0 -197
  81. data/bin/edit_json.rb +0 -9
  82. data/bin/prettify_json.rb +0 -75
  83. data/data/example.json +0 -1
  84. data/data/index.html +0 -38
  85. data/data/prototype.js +0 -4184
  86. data/ext/json/ext/generator/unicode.c +0 -180
  87. data/ext/json/ext/generator/unicode.h +0 -53
  88. data/ext/json/ext/parser/parser.rl +0 -737
  89. data/ext/json/ext/parser/unicode.c +0 -154
  90. data/ext/json/ext/parser/unicode.h +0 -58
  91. data/install.rb +0 -26
  92. data/lib/json/Array.xpm +0 -21
  93. data/lib/json/FalseClass.xpm +0 -21
  94. data/lib/json/Hash.xpm +0 -21
  95. data/lib/json/Key.xpm +0 -73
  96. data/lib/json/NilClass.xpm +0 -21
  97. data/lib/json/Numeric.xpm +0 -28
  98. data/lib/json/String.xpm +0 -96
  99. data/lib/json/TrueClass.xpm +0 -21
  100. data/lib/json/add/rails.rb +0 -58
  101. data/lib/json/editor.rb +0 -1371
  102. data/lib/json/json.xpm +0 -1499
  103. data/lib/json/pure/generator.rb +0 -443
  104. data/lib/json/pure/parser.rb +0 -303
  105. data/lib/json/pure.rb +0 -77
  106. data/tests/fixtures/fail1.json +0 -1
  107. data/tests/fixtures/fail10.json +0 -1
  108. data/tests/fixtures/fail11.json +0 -1
  109. data/tests/fixtures/fail12.json +0 -1
  110. data/tests/fixtures/fail13.json +0 -1
  111. data/tests/fixtures/fail14.json +0 -1
  112. data/tests/fixtures/fail18.json +0 -1
  113. data/tests/fixtures/fail19.json +0 -1
  114. data/tests/fixtures/fail2.json +0 -1
  115. data/tests/fixtures/fail20.json +0 -1
  116. data/tests/fixtures/fail21.json +0 -1
  117. data/tests/fixtures/fail22.json +0 -1
  118. data/tests/fixtures/fail23.json +0 -1
  119. data/tests/fixtures/fail24.json +0 -1
  120. data/tests/fixtures/fail25.json +0 -1
  121. data/tests/fixtures/fail27.json +0 -2
  122. data/tests/fixtures/fail28.json +0 -2
  123. data/tests/fixtures/fail3.json +0 -1
  124. data/tests/fixtures/fail4.json +0 -1
  125. data/tests/fixtures/fail5.json +0 -1
  126. data/tests/fixtures/fail6.json +0 -1
  127. data/tests/fixtures/fail7.json +0 -1
  128. data/tests/fixtures/fail8.json +0 -1
  129. data/tests/fixtures/fail9.json +0 -1
  130. data/tests/fixtures/pass1.json +0 -56
  131. data/tests/fixtures/pass15.json +0 -1
  132. data/tests/fixtures/pass16.json +0 -1
  133. data/tests/fixtures/pass17.json +0 -1
  134. data/tests/fixtures/pass2.json +0 -1
  135. data/tests/fixtures/pass26.json +0 -1
  136. data/tests/fixtures/pass3.json +0 -6
  137. data/tests/test_json.rb +0 -320
  138. data/tests/test_json_addition.rb +0 -164
  139. data/tests/test_json_encoding.rb +0 -67
  140. data/tests/test_json_fixtures.rb +0 -34
  141. data/tests/test_json_generate.rb +0 -120
  142. data/tests/test_json_rails.rb +0 -146
  143. data/tests/test_json_unicode.rb +0 -62
  144. data/tools/fuzz.rb +0 -139
  145. data/tools/server.rb +0 -61
data/lib/json/version.rb CHANGED
@@ -1,8 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module JSON
2
- # JSON version
3
- VERSION = '1.2.0'
4
- VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc:
5
- VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
6
- VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
7
- VERSION_BUILD = VERSION_ARRAY[2] # :nodoc:
4
+ VERSION = '2.19.8'
8
5
  end
data/lib/json.rb CHANGED
@@ -1,10 +1,675 @@
1
+ # frozen_string_literal: true
1
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_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
+ #
209
+ # ====== Output Options
210
+ #
211
+ # Option +freeze+ (boolean) specifies whether the returned objects will be frozen;
212
+ # defaults to +false+.
213
+ #
214
+ # Option +symbolize_names+ (boolean) specifies whether returned \Hash keys
215
+ # should be Symbols;
216
+ # defaults to +false+ (use Strings).
217
+ #
218
+ # With the default, +false+:
219
+ # source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}'
220
+ # ruby = JSON.parse(source)
221
+ # ruby # => {"a"=>"foo", "b"=>1.0, "c"=>true, "d"=>false, "e"=>nil}
222
+ # Use Symbols:
223
+ # ruby = JSON.parse(source, {symbolize_names: true})
224
+ # ruby # => {:a=>"foo", :b=>1.0, :c=>true, :d=>false, :e=>nil}
225
+ #
226
+ # ---
227
+ #
228
+ # Option +object_class+ (\Class) specifies the Ruby class to be used
229
+ # for each \JSON object;
230
+ # defaults to \Hash.
231
+ #
232
+ # With the default, \Hash:
233
+ # source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}'
234
+ # ruby = JSON.parse(source)
235
+ # ruby.class # => Hash
236
+ # Use class \OpenStruct:
237
+ # ruby = JSON.parse(source, {object_class: OpenStruct})
238
+ # ruby # => #<OpenStruct a="foo", b=1.0, c=true, d=false, e=nil>
239
+ #
240
+ # ---
241
+ #
242
+ # Option +array_class+ (\Class) specifies the Ruby class to be used
243
+ # for each \JSON array;
244
+ # defaults to \Array.
245
+ #
246
+ # With the default, \Array:
247
+ # source = '["foo", 1.0, true, false, null]'
248
+ # ruby = JSON.parse(source)
249
+ # ruby.class # => Array
250
+ # Use class \Set:
251
+ # ruby = JSON.parse(source, {array_class: Set})
252
+ # ruby # => #<Set: {"foo", 1.0, true, false, nil}>
253
+ #
254
+ # ---
255
+ #
256
+ # Option +create_additions+ (boolean) specifies whether to use \JSON additions in parsing.
257
+ # See {\JSON Additions}[#module-JSON-label-JSON+Additions].
258
+ #
259
+ # === Generating \JSON
260
+ #
261
+ # To generate a Ruby \String containing \JSON data,
262
+ # use method <tt>JSON.generate(source, opts)</tt>, where
263
+ # - +source+ is a Ruby object.
264
+ # - +opts+ is a \Hash object containing options
265
+ # that control both input allowed and output formatting.
266
+ #
267
+ # ==== Generating \JSON from Arrays
268
+ #
269
+ # When the source is a Ruby \Array, JSON.generate returns
270
+ # a \String containing a \JSON array:
271
+ # ruby = [0, 's', :foo]
272
+ # json = JSON.generate(ruby)
273
+ # json # => '[0,"s","foo"]'
274
+ #
275
+ # The Ruby \Array array may contain nested arrays, hashes, and scalars
276
+ # to any depth:
277
+ # ruby = [0, [1, 2], {foo: 3, bar: 4}]
278
+ # json = JSON.generate(ruby)
279
+ # json # => '[0,[1,2],{"foo":3,"bar":4}]'
280
+ #
281
+ # ==== Generating \JSON from Hashes
282
+ #
283
+ # When the source is a Ruby \Hash, JSON.generate returns
284
+ # a \String containing a \JSON object:
285
+ # ruby = {foo: 0, bar: 's', baz: :bat}
286
+ # json = JSON.generate(ruby)
287
+ # json # => '{"foo":0,"bar":"s","baz":"bat"}'
288
+ #
289
+ # The Ruby \Hash array may contain nested arrays, hashes, and scalars
290
+ # to any depth:
291
+ # ruby = {foo: [0, 1], bar: {baz: 2, bat: 3}, bam: :bad}
292
+ # json = JSON.generate(ruby)
293
+ # json # => '{"foo":[0,1],"bar":{"baz":2,"bat":3},"bam":"bad"}'
294
+ #
295
+ # ==== Generating \JSON from Other Objects
296
+ #
297
+ # When the source is neither an \Array nor a \Hash,
298
+ # the generated \JSON data depends on the class of the source.
299
+ #
300
+ # When the source is a Ruby \Integer or \Float, JSON.generate returns
301
+ # a \String containing a \JSON number:
302
+ # JSON.generate(42) # => '42'
303
+ # JSON.generate(0.42) # => '0.42'
304
+ #
305
+ # When the source is a Ruby \String, JSON.generate returns
306
+ # a \String containing a \JSON string (with double-quotes):
307
+ # JSON.generate('A string') # => '"A string"'
308
+ #
309
+ # When the source is +true+, +false+ or +nil+, JSON.generate returns
310
+ # a \String containing the corresponding \JSON token:
311
+ # JSON.generate(true) # => 'true'
312
+ # JSON.generate(false) # => 'false'
313
+ # JSON.generate(nil) # => 'null'
314
+ #
315
+ # When the source is none of the above, JSON.generate returns
316
+ # a \String containing a \JSON string representation of the source:
317
+ # JSON.generate(:foo) # => '"foo"'
318
+ # JSON.generate(Complex(0, 0)) # => '"0+0i"'
319
+ # JSON.generate(Dir.new('.')) # => '"#<Dir>"'
320
+ #
321
+ # ==== Generating Options
322
+ #
323
+ # ====== Input Options
324
+ #
325
+ # Option +allow_nan+ (boolean) specifies whether
326
+ # +NaN+, +Infinity+, and <tt>-Infinity</tt> may be generated;
327
+ # defaults to +false+.
328
+ #
329
+ # With the default, +false+:
330
+ # # Raises JSON::GeneratorError (920: NaN not allowed in JSON):
331
+ # JSON.generate(JSON::NaN)
332
+ # # Raises JSON::GeneratorError (917: Infinity not allowed in JSON):
333
+ # JSON.generate(JSON::Infinity)
334
+ # # Raises JSON::GeneratorError (917: -Infinity not allowed in JSON):
335
+ # JSON.generate(JSON::MinusInfinity)
336
+ #
337
+ # Allow:
338
+ # ruby = [Float::NAN, Float::INFINITY, JSON::NaN, JSON::Infinity, JSON::MinusInfinity]
339
+ # JSON.generate(ruby, allow_nan: true) # => '[NaN,Infinity,NaN,Infinity,-Infinity]'
340
+ #
341
+ # ---
342
+ #
343
+ # Option +allow_duplicate_key+ (boolean) specifies whether
344
+ # hashes with duplicate keys should be allowed or produce an error.
345
+ # defaults to emit a deprecation warning.
346
+ #
347
+ # With the default, (not set):
348
+ # Warning[:deprecated] = true
349
+ # JSON.generate({ foo: 1, "foo" => 2 })
350
+ # # warning: detected duplicate key "foo" in {foo: 1, "foo" => 2}.
351
+ # # This will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`
352
+ # # => '{"foo":1,"foo":2}'
353
+ #
354
+ # With <tt>false</tt>
355
+ # JSON.generate({ foo: 1, "foo" => 2 }, allow_duplicate_key: false)
356
+ # # detected duplicate key "foo" in {foo: 1, "foo" => 2} (JSON::GeneratorError)
357
+ #
358
+ # In version 3.0, <tt>false</tt> will become the default.
359
+ #
360
+ # ---
361
+ #
362
+ # Option +max_nesting+ (\Integer) specifies the maximum nesting depth
363
+ # in +obj+; defaults to +100+.
364
+ #
365
+ # With the default, +100+:
366
+ # obj = [[[[[[0]]]]]]
367
+ # JSON.generate(obj) # => '[[[[[[0]]]]]]'
368
+ #
369
+ # Too deep:
370
+ # # Raises JSON::NestingError (nesting of 2 is too deep):
371
+ # JSON.generate(obj, max_nesting: 2)
372
+ #
373
+ # ====== Escaping Options
374
+ #
375
+ # Options +script_safe+ (boolean) specifies wether <tt>'\u2028'</tt>, <tt>'\u2029'</tt>
376
+ # and <tt>'/'</tt> should be escaped as to make the JSON object safe to interpolate in script
377
+ # tags.
378
+ #
379
+ # Options +ascii_only+ (boolean) specifies wether all characters outside the ASCII range
380
+ # should be escaped.
381
+ #
382
+ # ====== Output Options
383
+ #
384
+ # The default formatting options generate the most compact
385
+ # \JSON data, all on one line and with no whitespace.
386
+ #
387
+ # You can use these formatting options to generate
388
+ # \JSON data in a more open format, using whitespace.
389
+ # See also JSON.pretty_generate.
390
+ #
391
+ # - Option +array_nl+ (\String) specifies a string (usually a newline)
392
+ # to be inserted after each \JSON array; defaults to the empty \String, <tt>''</tt>.
393
+ # - Option +object_nl+ (\String) specifies a string (usually a newline)
394
+ # to be inserted after each \JSON object; defaults to the empty \String, <tt>''</tt>.
395
+ # - Option +indent+ (\String) specifies the string (usually spaces) to be
396
+ # used for indentation; defaults to the empty \String, <tt>''</tt>;
397
+ # defaults to the empty \String, <tt>''</tt>;
398
+ # has no effect unless options +array_nl+ or +object_nl+ specify newlines.
399
+ # - Option +space+ (\String) specifies a string (usually a space) to be
400
+ # inserted after the colon in each \JSON object's pair;
401
+ # defaults to the empty \String, <tt>''</tt>.
402
+ # - Option +space_before+ (\String) specifies a string (usually a space) to be
403
+ # inserted before the colon in each \JSON object's pair;
404
+ # defaults to the empty \String, <tt>''</tt>.
405
+ #
406
+ # In this example, +obj+ is used first to generate the shortest
407
+ # \JSON data (no whitespace), then again with all formatting options
408
+ # specified:
409
+ #
410
+ # obj = {foo: [:bar, :baz], bat: {bam: 0, bad: 1}}
411
+ # json = JSON.generate(obj)
412
+ # puts 'Compact:', json
413
+ # opts = {
414
+ # array_nl: "\n",
415
+ # object_nl: "\n",
416
+ # indent: ' ',
417
+ # space_before: ' ',
418
+ # space: ' '
419
+ # }
420
+ # puts 'Open:', JSON.generate(obj, opts)
421
+ #
422
+ # Output:
423
+ # Compact:
424
+ # {"foo":["bar","baz"],"bat":{"bam":0,"bad":1}}
425
+ # Open:
426
+ # {
427
+ # "foo" : [
428
+ # "bar",
429
+ # "baz"
430
+ # ],
431
+ # "bat" : {
432
+ # "bam" : 0,
433
+ # "bad" : 1
434
+ # }
435
+ # }
436
+ #
437
+ # == \JSON Additions
438
+ #
439
+ # Note that JSON Additions must only be used with trusted data, and is
440
+ # deprecated.
441
+ #
442
+ # When you "round trip" a non-\String object from Ruby to \JSON and back,
443
+ # you have a new \String, instead of the object you began with:
444
+ # ruby0 = Range.new(0, 2)
445
+ # json = JSON.generate(ruby0)
446
+ # json # => '0..2"'
447
+ # ruby1 = JSON.parse(json)
448
+ # ruby1 # => '0..2'
449
+ # ruby1.class # => String
450
+ #
451
+ # You can use \JSON _additions_ to preserve the original object.
452
+ # The addition is an extension of a ruby class, so that:
453
+ # - \JSON.generate stores more information in the \JSON string.
454
+ # - \JSON.parse, called with option +create_additions+,
455
+ # uses that information to create a proper Ruby object.
456
+ #
457
+ # This example shows a \Range being generated into \JSON
458
+ # and parsed back into Ruby, both without and with
459
+ # the addition for \Range:
460
+ # ruby = Range.new(0, 2)
461
+ # # This passage does not use the addition for Range.
462
+ # json0 = JSON.generate(ruby)
463
+ # ruby0 = JSON.parse(json0)
464
+ # # This passage uses the addition for Range.
465
+ # require 'json/add/range'
466
+ # json1 = JSON.generate(ruby)
467
+ # ruby1 = JSON.parse(json1, create_additions: true)
468
+ # # Make a nice display.
469
+ # display = <<~EOT
470
+ # Generated JSON:
471
+ # Without addition: #{json0} (#{json0.class})
472
+ # With addition: #{json1} (#{json1.class})
473
+ # Parsed JSON:
474
+ # Without addition: #{ruby0.inspect} (#{ruby0.class})
475
+ # With addition: #{ruby1.inspect} (#{ruby1.class})
476
+ # EOT
477
+ # puts display
478
+ #
479
+ # This output shows the different results:
480
+ # Generated JSON:
481
+ # Without addition: "0..2" (String)
482
+ # With addition: {"json_class":"Range","a":[0,2,false]} (String)
483
+ # Parsed JSON:
484
+ # Without addition: "0..2" (String)
485
+ # With addition: 0..2 (Range)
486
+ #
487
+ # The \JSON module includes additions for certain classes.
488
+ # You can also craft custom additions.
489
+ # See {Custom \JSON Additions}[#module-JSON-label-Custom+JSON+Additions].
490
+ #
491
+ # === Built-in Additions
492
+ #
493
+ # The \JSON module includes additions for certain classes.
494
+ # To use an addition, +require+ its source:
495
+ # - BigDecimal: <tt>require 'json/add/bigdecimal'</tt>
496
+ # - Complex: <tt>require 'json/add/complex'</tt>
497
+ # - Date: <tt>require 'json/add/date'</tt>
498
+ # - DateTime: <tt>require 'json/add/date_time'</tt>
499
+ # - Exception: <tt>require 'json/add/exception'</tt>
500
+ # - OpenStruct: <tt>require 'json/add/ostruct'</tt>
501
+ # - Range: <tt>require 'json/add/range'</tt>
502
+ # - Rational: <tt>require 'json/add/rational'</tt>
503
+ # - Regexp: <tt>require 'json/add/regexp'</tt>
504
+ # - Set: <tt>require 'json/add/set'</tt>
505
+ # - Struct: <tt>require 'json/add/struct'</tt>
506
+ # - Symbol: <tt>require 'json/add/symbol'</tt>
507
+ # - Time: <tt>require 'json/add/time'</tt>
508
+ #
509
+ # To reduce punctuation clutter, the examples below
510
+ # show the generated \JSON via +puts+, rather than the usual +inspect+,
511
+ #
512
+ # \BigDecimal:
513
+ # require 'json/add/bigdecimal'
514
+ # ruby0 = BigDecimal(0) # 0.0
515
+ # json = JSON.generate(ruby0) # {"json_class":"BigDecimal","b":"27:0.0"}
516
+ # ruby1 = JSON.parse(json, create_additions: true) # 0.0
517
+ # ruby1.class # => BigDecimal
518
+ #
519
+ # \Complex:
520
+ # require 'json/add/complex'
521
+ # ruby0 = Complex(1+0i) # 1+0i
522
+ # json = JSON.generate(ruby0) # {"json_class":"Complex","r":1,"i":0}
523
+ # ruby1 = JSON.parse(json, create_additions: true) # 1+0i
524
+ # ruby1.class # Complex
525
+ #
526
+ # \Date:
527
+ # require 'json/add/date'
528
+ # ruby0 = Date.today # 2020-05-02
529
+ # json = JSON.generate(ruby0) # {"json_class":"Date","y":2020,"m":5,"d":2,"sg":2299161.0}
530
+ # ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02
531
+ # ruby1.class # Date
532
+ #
533
+ # \DateTime:
534
+ # require 'json/add/date_time'
535
+ # ruby0 = DateTime.now # 2020-05-02T10:38:13-05:00
536
+ # 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}
537
+ # ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02T10:38:13-05:00
538
+ # ruby1.class # DateTime
539
+ #
540
+ # \Exception (and its subclasses including \RuntimeError):
541
+ # require 'json/add/exception'
542
+ # ruby0 = Exception.new('A message') # A message
543
+ # json = JSON.generate(ruby0) # {"json_class":"Exception","m":"A message","b":null}
544
+ # ruby1 = JSON.parse(json, create_additions: true) # A message
545
+ # ruby1.class # Exception
546
+ # ruby0 = RuntimeError.new('Another message') # Another message
547
+ # json = JSON.generate(ruby0) # {"json_class":"RuntimeError","m":"Another message","b":null}
548
+ # ruby1 = JSON.parse(json, create_additions: true) # Another message
549
+ # ruby1.class # RuntimeError
550
+ #
551
+ # \OpenStruct:
552
+ # require 'json/add/ostruct'
553
+ # ruby0 = OpenStruct.new(name: 'Matz', language: 'Ruby') # #<OpenStruct name="Matz", language="Ruby">
554
+ # json = JSON.generate(ruby0) # {"json_class":"OpenStruct","t":{"name":"Matz","language":"Ruby"}}
555
+ # ruby1 = JSON.parse(json, create_additions: true) # #<OpenStruct name="Matz", language="Ruby">
556
+ # ruby1.class # OpenStruct
557
+ #
558
+ # \Range:
559
+ # require 'json/add/range'
560
+ # ruby0 = Range.new(0, 2) # 0..2
561
+ # json = JSON.generate(ruby0) # {"json_class":"Range","a":[0,2,false]}
562
+ # ruby1 = JSON.parse(json, create_additions: true) # 0..2
563
+ # ruby1.class # Range
564
+ #
565
+ # \Rational:
566
+ # require 'json/add/rational'
567
+ # ruby0 = Rational(1, 3) # 1/3
568
+ # json = JSON.generate(ruby0) # {"json_class":"Rational","n":1,"d":3}
569
+ # ruby1 = JSON.parse(json, create_additions: true) # 1/3
570
+ # ruby1.class # Rational
571
+ #
572
+ # \Regexp:
573
+ # require 'json/add/regexp'
574
+ # ruby0 = Regexp.new('foo') # (?-mix:foo)
575
+ # json = JSON.generate(ruby0) # {"json_class":"Regexp","o":0,"s":"foo"}
576
+ # ruby1 = JSON.parse(json, create_additions: true) # (?-mix:foo)
577
+ # ruby1.class # Regexp
578
+ #
579
+ # \Set:
580
+ # require 'json/add/set'
581
+ # ruby0 = Set.new([0, 1, 2]) # #<Set: {0, 1, 2}>
582
+ # json = JSON.generate(ruby0) # {"json_class":"Set","a":[0,1,2]}
583
+ # ruby1 = JSON.parse(json, create_additions: true) # #<Set: {0, 1, 2}>
584
+ # ruby1.class # Set
585
+ #
586
+ # \Struct:
587
+ # require 'json/add/struct'
588
+ # Customer = Struct.new(:name, :address) # Customer
589
+ # ruby0 = Customer.new("Dave", "123 Main") # #<struct Customer name="Dave", address="123 Main">
590
+ # json = JSON.generate(ruby0) # {"json_class":"Customer","v":["Dave","123 Main"]}
591
+ # ruby1 = JSON.parse(json, create_additions: true) # #<struct Customer name="Dave", address="123 Main">
592
+ # ruby1.class # Customer
593
+ #
594
+ # \Symbol:
595
+ # require 'json/add/symbol'
596
+ # ruby0 = :foo # foo
597
+ # json = JSON.generate(ruby0) # {"json_class":"Symbol","s":"foo"}
598
+ # ruby1 = JSON.parse(json, create_additions: true) # foo
599
+ # ruby1.class # Symbol
600
+ #
601
+ # \Time:
602
+ # require 'json/add/time'
603
+ # ruby0 = Time.now # 2020-05-02 11:28:26 -0500
604
+ # json = JSON.generate(ruby0) # {"json_class":"Time","s":1588436906,"n":840560000}
605
+ # ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02 11:28:26 -0500
606
+ # ruby1.class # Time
607
+ #
608
+ #
609
+ # === Custom \JSON Additions
610
+ #
611
+ # In addition to the \JSON additions provided,
612
+ # you can craft \JSON additions of your own,
613
+ # either for Ruby built-in classes or for user-defined classes.
614
+ #
615
+ # Here's a user-defined class +Foo+:
616
+ # class Foo
617
+ # attr_accessor :bar, :baz
618
+ # def initialize(bar, baz)
619
+ # self.bar = bar
620
+ # self.baz = baz
621
+ # end
622
+ # end
623
+ #
624
+ # Here's the \JSON addition for it:
625
+ # # Extend class Foo with JSON addition.
626
+ # class Foo
627
+ # # Serialize Foo object with its class name and arguments
628
+ # def to_json(*args)
629
+ # {
630
+ # JSON.create_id => self.class.name,
631
+ # 'a' => [ bar, baz ]
632
+ # }.to_json(*args)
633
+ # end
634
+ # # Deserialize JSON string by constructing new Foo object with arguments.
635
+ # def self.json_create(object)
636
+ # new(*object['a'])
637
+ # end
638
+ # end
639
+ #
640
+ # Demonstration:
641
+ # require 'json'
642
+ # # This Foo object has no custom addition.
643
+ # foo0 = Foo.new(0, 1)
644
+ # json0 = JSON.generate(foo0)
645
+ # obj0 = JSON.parse(json0)
646
+ # # Lood the custom addition.
647
+ # require_relative 'foo_addition'
648
+ # # This foo has the custom addition.
649
+ # foo1 = Foo.new(0, 1)
650
+ # json1 = JSON.generate(foo1)
651
+ # obj1 = JSON.parse(json1, create_additions: true)
652
+ # # Make a nice display.
653
+ # display = <<~EOT
654
+ # Generated JSON:
655
+ # Without custom addition: #{json0} (#{json0.class})
656
+ # With custom addition: #{json1} (#{json1.class})
657
+ # Parsed JSON:
658
+ # Without custom addition: #{obj0.inspect} (#{obj0.class})
659
+ # With custom addition: #{obj1.inspect} (#{obj1.class})
660
+ # EOT
661
+ # puts display
662
+ #
663
+ # Output:
664
+ #
665
+ # Generated JSON:
666
+ # Without custom addition: "#<Foo:0x0000000006534e80>" (String)
667
+ # With custom addition: {"json_class":"Foo","a":[0,1]} (String)
668
+ # Parsed JSON:
669
+ # Without custom addition: "#<Foo:0x0000000006534e80>" (String)
670
+ # With custom addition: #<Foo:0x0000000006473bb8 @bar=0, @baz=1> (Foo)
671
+ #
2
672
  module JSON
3
673
  require 'json/version'
4
-
5
- begin
6
- require 'json/ext'
7
- rescue LoadError
8
- require 'json/pure'
9
- end
674
+ require 'json/ext'
10
675
  end