json_pure 2.7.0 → 2.8.1

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.
@@ -1,71 +0,0 @@
1
- #frozen_string_literal: false
2
- require 'ostruct'
3
-
4
- module JSON
5
- class GenericObject < OpenStruct
6
- class << self
7
- alias [] new
8
-
9
- def json_creatable?
10
- @json_creatable
11
- end
12
-
13
- attr_writer :json_creatable
14
-
15
- def json_create(data)
16
- data = data.dup
17
- data.delete JSON.create_id
18
- self[data]
19
- end
20
-
21
- def from_hash(object)
22
- case
23
- when object.respond_to?(:to_hash)
24
- result = new
25
- object.to_hash.each do |key, value|
26
- result[key] = from_hash(value)
27
- end
28
- result
29
- when object.respond_to?(:to_ary)
30
- object.to_ary.map { |a| from_hash(a) }
31
- else
32
- object
33
- end
34
- end
35
-
36
- def load(source, proc = nil, opts = {})
37
- result = ::JSON.load(source, proc, opts.merge(:object_class => self))
38
- result.nil? ? new : result
39
- end
40
-
41
- def dump(obj, *args)
42
- ::JSON.dump(obj, *args)
43
- end
44
- end
45
- self.json_creatable = false
46
-
47
- def to_hash
48
- table
49
- end
50
-
51
- def [](name)
52
- __send__(name)
53
- end unless method_defined?(:[])
54
-
55
- def []=(name, value)
56
- __send__("#{name}=", value)
57
- end unless method_defined?(:[]=)
58
-
59
- def |(other)
60
- self.class[other.to_hash.merge(to_hash)]
61
- end
62
-
63
- def as_json(*)
64
- { JSON.create_id => self.class.name }.merge to_hash
65
- end
66
-
67
- def to_json(*a)
68
- as_json.to_json(*a)
69
- end
70
- end
71
- end
@@ -1,513 +0,0 @@
1
- #frozen_string_literal: false
2
- module JSON
3
- MAP = {
4
- "\x0" => '\u0000',
5
- "\x1" => '\u0001',
6
- "\x2" => '\u0002',
7
- "\x3" => '\u0003',
8
- "\x4" => '\u0004',
9
- "\x5" => '\u0005',
10
- "\x6" => '\u0006',
11
- "\x7" => '\u0007',
12
- "\b" => '\b',
13
- "\t" => '\t',
14
- "\n" => '\n',
15
- "\xb" => '\u000b',
16
- "\f" => '\f',
17
- "\r" => '\r',
18
- "\xe" => '\u000e',
19
- "\xf" => '\u000f',
20
- "\x10" => '\u0010',
21
- "\x11" => '\u0011',
22
- "\x12" => '\u0012',
23
- "\x13" => '\u0013',
24
- "\x14" => '\u0014',
25
- "\x15" => '\u0015',
26
- "\x16" => '\u0016',
27
- "\x17" => '\u0017',
28
- "\x18" => '\u0018',
29
- "\x19" => '\u0019',
30
- "\x1a" => '\u001a',
31
- "\x1b" => '\u001b',
32
- "\x1c" => '\u001c',
33
- "\x1d" => '\u001d',
34
- "\x1e" => '\u001e',
35
- "\x1f" => '\u001f',
36
- '"' => '\"',
37
- '\\' => '\\\\',
38
- } # :nodoc:
39
-
40
- ESCAPE_PATTERN = /[\/"\\\x0-\x1f]/n # :nodoc:
41
-
42
- SCRIPT_SAFE_MAP = MAP.merge(
43
- '/' => '\\/',
44
- "\u2028".b => '\u2028',
45
- "\u2029".b => '\u2029',
46
- )
47
-
48
- SCRIPT_SAFE_ESCAPE_PATTERN = Regexp.union(ESCAPE_PATTERN, "\u2028".b, "\u2029".b)
49
-
50
- # Convert a UTF8 encoded Ruby string _string_ to a JSON string, encoded with
51
- # UTF16 big endian characters as \u????, and return it.
52
- def utf8_to_json(string, script_safe = false) # :nodoc:
53
- string = string.dup
54
- string.force_encoding(::Encoding::ASCII_8BIT)
55
- if script_safe
56
- string.gsub!(SCRIPT_SAFE_ESCAPE_PATTERN) { SCRIPT_SAFE_MAP[$&] || $& }
57
- else
58
- string.gsub!(ESCAPE_PATTERN) { MAP[$&] || $& }
59
- end
60
- string.force_encoding(::Encoding::UTF_8)
61
- string
62
- end
63
-
64
- def utf8_to_json_ascii(string, script_safe = false) # :nodoc:
65
- string = string.dup
66
- string.force_encoding(::Encoding::ASCII_8BIT)
67
- map = script_safe ? SCRIPT_SAFE_MAP : MAP
68
- string.gsub!(/[\/"\\\x0-\x1f]/n) { map[$&] || $& }
69
- string.gsub!(/(
70
- (?:
71
- [\xc2-\xdf][\x80-\xbf] |
72
- [\xe0-\xef][\x80-\xbf]{2} |
73
- [\xf0-\xf4][\x80-\xbf]{3}
74
- )+ |
75
- [\x80-\xc1\xf5-\xff] # invalid
76
- )/nx) { |c|
77
- c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
78
- s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0]
79
- s.force_encoding(::Encoding::ASCII_8BIT)
80
- s.gsub!(/.{4}/n, '\\\\u\&')
81
- s.force_encoding(::Encoding::UTF_8)
82
- }
83
- string.force_encoding(::Encoding::UTF_8)
84
- string
85
- rescue => e
86
- raise GeneratorError.wrap(e)
87
- end
88
-
89
- def valid_utf8?(string)
90
- encoding = string.encoding
91
- (encoding == Encoding::UTF_8 || encoding == Encoding::ASCII) &&
92
- string.valid_encoding?
93
- end
94
- module_function :utf8_to_json, :utf8_to_json_ascii, :valid_utf8?
95
-
96
- module Pure
97
- module Generator
98
- # This class is used to create State instances, that are use to hold data
99
- # while generating a JSON text from a Ruby data structure.
100
- class State
101
- # Creates a State object from _opts_, which ought to be Hash to create
102
- # a new State instance configured by _opts_, something else to create
103
- # an unconfigured instance. If _opts_ is a State object, it is just
104
- # returned.
105
- def self.from_state(opts)
106
- case
107
- when self === opts
108
- opts
109
- when opts.respond_to?(:to_hash)
110
- new(opts.to_hash)
111
- when opts.respond_to?(:to_h)
112
- new(opts.to_h)
113
- else
114
- SAFE_STATE_PROTOTYPE.dup
115
- end
116
- end
117
-
118
- # Instantiates a new State object, configured by _opts_.
119
- #
120
- # _opts_ can have the following keys:
121
- #
122
- # * *indent*: a string used to indent levels (default: ''),
123
- # * *space*: a string that is put after, a : or , delimiter (default: ''),
124
- # * *space_before*: a string that is put before a : pair delimiter (default: ''),
125
- # * *object_nl*: a string that is put at the end of a JSON object (default: ''),
126
- # * *array_nl*: a string that is put at the end of a JSON array (default: ''),
127
- # * *script_safe*: true if U+2028, U+2029 and forward slash (/) should be escaped
128
- # as to make the JSON object safe to interpolate in a script tag (default: false).
129
- # * *check_circular*: is deprecated now, use the :max_nesting option instead,
130
- # * *max_nesting*: sets the maximum level of data structure nesting in
131
- # the generated JSON, max_nesting = 0 if no maximum should be checked.
132
- # * *allow_nan*: true if NaN, Infinity, and -Infinity should be
133
- # generated, otherwise an exception is thrown, if these values are
134
- # encountered. This options defaults to false.
135
- def initialize(opts = {})
136
- @indent = ''
137
- @space = ''
138
- @space_before = ''
139
- @object_nl = ''
140
- @array_nl = ''
141
- @allow_nan = false
142
- @ascii_only = false
143
- @script_safe = false
144
- @strict = false
145
- @buffer_initial_length = 1024
146
- configure opts
147
- end
148
-
149
- # This string is used to indent levels in the JSON text.
150
- attr_accessor :indent
151
-
152
- # This string is used to insert a space between the tokens in a JSON
153
- # string.
154
- attr_accessor :space
155
-
156
- # This string is used to insert a space before the ':' in JSON objects.
157
- attr_accessor :space_before
158
-
159
- # This string is put at the end of a line that holds a JSON object (or
160
- # Hash).
161
- attr_accessor :object_nl
162
-
163
- # This string is put at the end of a line that holds a JSON array.
164
- attr_accessor :array_nl
165
-
166
- # This integer returns the maximum level of data structure nesting in
167
- # the generated JSON, max_nesting = 0 if no maximum is checked.
168
- attr_accessor :max_nesting
169
-
170
- # If this attribute is set to true, forward slashes will be escaped in
171
- # all json strings.
172
- attr_accessor :script_safe
173
-
174
- # If this attribute is set to true, attempting to serialize types not
175
- # supported by the JSON spec will raise a JSON::GeneratorError
176
- attr_accessor :strict
177
-
178
- # :stopdoc:
179
- attr_reader :buffer_initial_length
180
-
181
- def buffer_initial_length=(length)
182
- if length > 0
183
- @buffer_initial_length = length
184
- end
185
- end
186
- # :startdoc:
187
-
188
- # This integer returns the current depth data structure nesting in the
189
- # generated JSON.
190
- attr_accessor :depth
191
-
192
- def check_max_nesting # :nodoc:
193
- return if @max_nesting.zero?
194
- current_nesting = depth + 1
195
- current_nesting > @max_nesting and
196
- raise NestingError, "nesting of #{current_nesting} is too deep"
197
- end
198
-
199
- # Returns true, if circular data structures are checked,
200
- # otherwise returns false.
201
- def check_circular?
202
- !@max_nesting.zero?
203
- end
204
-
205
- # Returns true if NaN, Infinity, and -Infinity should be considered as
206
- # valid JSON and output.
207
- def allow_nan?
208
- @allow_nan
209
- end
210
-
211
- # Returns true, if only ASCII characters should be generated. Otherwise
212
- # returns false.
213
- def ascii_only?
214
- @ascii_only
215
- end
216
-
217
- # Returns true, if forward slashes are escaped. Otherwise returns false.
218
- def script_safe?
219
- @script_safe
220
- end
221
-
222
- # Returns true, if forward slashes are escaped. Otherwise returns false.
223
- def strict?
224
- @strict
225
- end
226
-
227
- # Configure this State instance with the Hash _opts_, and return
228
- # itself.
229
- def configure(opts)
230
- if opts.respond_to?(:to_hash)
231
- opts = opts.to_hash
232
- elsif opts.respond_to?(:to_h)
233
- opts = opts.to_h
234
- else
235
- raise TypeError, "can't convert #{opts.class} into Hash"
236
- end
237
- opts.each do |key, value|
238
- instance_variable_set "@#{key}", value
239
- end
240
- @indent = opts[:indent] if opts.key?(:indent)
241
- @space = opts[:space] if opts.key?(:space)
242
- @space_before = opts[:space_before] if opts.key?(:space_before)
243
- @object_nl = opts[:object_nl] if opts.key?(:object_nl)
244
- @array_nl = opts[:array_nl] if opts.key?(:array_nl)
245
- @allow_nan = !!opts[:allow_nan] if opts.key?(:allow_nan)
246
- @ascii_only = opts[:ascii_only] if opts.key?(:ascii_only)
247
- @depth = opts[:depth] || 0
248
- @buffer_initial_length ||= opts[:buffer_initial_length]
249
-
250
- @script_safe = if opts.key?(:script_safe)
251
- !!opts[:script_safe]
252
- elsif opts.key?(:escape_slash)
253
- !!opts[:escape_slash]
254
- else
255
- false
256
- end
257
-
258
- @strict = !!opts[:strict] if opts.key?(:strict)
259
-
260
- if !opts.key?(:max_nesting) # defaults to 100
261
- @max_nesting = 100
262
- elsif opts[:max_nesting]
263
- @max_nesting = opts[:max_nesting]
264
- else
265
- @max_nesting = 0
266
- end
267
- self
268
- end
269
- alias merge configure
270
-
271
- # Returns the configuration instance variables as a hash, that can be
272
- # passed to the configure method.
273
- def to_h
274
- result = {}
275
- instance_variables.each do |iv|
276
- iv = iv.to_s[1..-1]
277
- result[iv.to_sym] = self[iv]
278
- end
279
- result
280
- end
281
-
282
- alias to_hash to_h
283
-
284
- # Generates a valid JSON document from object +obj+ and
285
- # returns the result. If no valid JSON document can be
286
- # created this method raises a
287
- # GeneratorError exception.
288
- def generate(obj)
289
- result = obj.to_json(self)
290
- JSON.valid_utf8?(result) or raise GeneratorError,
291
- "source sequence #{result.inspect} is illegal/malformed utf-8"
292
- result
293
- end
294
-
295
- # Return the value returned by method +name+.
296
- def [](name)
297
- if respond_to?(name)
298
- __send__(name)
299
- else
300
- instance_variable_get("@#{name}") if
301
- instance_variables.include?("@#{name}".to_sym) # avoid warning
302
- end
303
- end
304
-
305
- def []=(name, value)
306
- if respond_to?(name_writer = "#{name}=")
307
- __send__ name_writer, value
308
- else
309
- instance_variable_set "@#{name}", value
310
- end
311
- end
312
- end
313
-
314
- module GeneratorMethods
315
- module Object
316
- # Converts this object to a string (calling #to_s), converts
317
- # it to a JSON string, and returns the result. This is a fallback, if no
318
- # special method #to_json was defined for some object.
319
- def to_json(generator_state)
320
- if generator_state.strict?
321
- raise GeneratorError, "#{self.class} not allowed in JSON"
322
- else
323
- to_s.to_json
324
- end
325
- end
326
- end
327
-
328
- module Hash
329
- # Returns a JSON string containing a JSON object, that is unparsed from
330
- # this Hash instance.
331
- # _state_ is a JSON::State object, that can also be used to configure the
332
- # produced JSON string output further.
333
- # _depth_ is used to find out nesting depth, to indent accordingly.
334
- def to_json(state = nil, *)
335
- state = State.from_state(state)
336
- state.check_max_nesting
337
- json_transform(state)
338
- end
339
-
340
- private
341
-
342
- def json_shift(state)
343
- state.object_nl.empty? or return ''
344
- state.indent * state.depth
345
- end
346
-
347
- def json_transform(state)
348
- delim = ",#{state.object_nl}"
349
- result = "{#{state.object_nl}"
350
- depth = state.depth += 1
351
- first = true
352
- indent = !state.object_nl.empty?
353
- each { |key, value|
354
- result << delim unless first
355
- result << state.indent * depth if indent
356
- result = "#{result}#{key.to_s.to_json(state)}#{state.space_before}:#{state.space}"
357
- if state.strict?
358
- raise GeneratorError, "#{value.class} not allowed in JSON"
359
- elsif value.respond_to?(:to_json)
360
- result << value.to_json(state)
361
- else
362
- result << %{"#{String(value)}"}
363
- end
364
- first = false
365
- }
366
- depth = state.depth -= 1
367
- unless first
368
- result << state.object_nl
369
- result << state.indent * depth if indent
370
- end
371
- result << '}'
372
- result
373
- end
374
- end
375
-
376
- module Array
377
- # Returns a JSON string containing a JSON array, that is unparsed from
378
- # this Array instance.
379
- # _state_ is a JSON::State object, that can also be used to configure the
380
- # produced JSON string output further.
381
- def to_json(state = nil, *)
382
- state = State.from_state(state)
383
- state.check_max_nesting
384
- json_transform(state)
385
- end
386
-
387
- private
388
-
389
- def json_transform(state)
390
- delim = ','
391
- delim << state.array_nl
392
- result = '['
393
- result << state.array_nl
394
- depth = state.depth += 1
395
- first = true
396
- indent = !state.array_nl.empty?
397
- each { |value|
398
- result << delim unless first
399
- result << state.indent * depth if indent
400
- if state.strict?
401
- raise GeneratorError, "#{value.class} not allowed in JSON"
402
- elsif value.respond_to?(:to_json)
403
- result << value.to_json(state)
404
- else
405
- result << %{"#{String(value)}"}
406
- end
407
- first = false
408
- }
409
- depth = state.depth -= 1
410
- result << state.array_nl
411
- result << state.indent * depth if indent
412
- result << ']'
413
- end
414
- end
415
-
416
- module Integer
417
- # Returns a JSON string representation for this Integer number.
418
- def to_json(*) to_s end
419
- end
420
-
421
- module Float
422
- # Returns a JSON string representation for this Float number.
423
- def to_json(state = nil, *)
424
- state = State.from_state(state)
425
- case
426
- when infinite?
427
- if state.allow_nan?
428
- to_s
429
- else
430
- raise GeneratorError, "#{self} not allowed in JSON"
431
- end
432
- when nan?
433
- if state.allow_nan?
434
- to_s
435
- else
436
- raise GeneratorError, "#{self} not allowed in JSON"
437
- end
438
- else
439
- to_s
440
- end
441
- end
442
- end
443
-
444
- module String
445
- # This string should be encoded with UTF-8 A call to this method
446
- # returns a JSON string encoded with UTF16 big endian characters as
447
- # \u????.
448
- def to_json(state = nil, *args)
449
- state = State.from_state(state)
450
- if encoding == ::Encoding::UTF_8
451
- string = self
452
- else
453
- string = encode(::Encoding::UTF_8)
454
- end
455
- if state.ascii_only?
456
- '"' << JSON.utf8_to_json_ascii(string, state.script_safe) << '"'
457
- else
458
- '"' << JSON.utf8_to_json(string, state.script_safe) << '"'
459
- end
460
- end
461
-
462
- # Module that holds the extending methods if, the String module is
463
- # included.
464
- module Extend
465
- # Raw Strings are JSON Objects (the raw bytes are stored in an
466
- # array for the key "raw"). The Ruby String can be created by this
467
- # module method.
468
- def json_create(o)
469
- o['raw'].pack('C*')
470
- end
471
- end
472
-
473
- # Extends _modul_ with the String::Extend module.
474
- def self.included(modul)
475
- modul.extend Extend
476
- end
477
-
478
- # This method creates a raw object hash, that can be nested into
479
- # other data structures and will be unparsed as a raw string. This
480
- # method should be used, if you want to convert raw strings to JSON
481
- # instead of UTF-8 strings, e. g. binary data.
482
- def to_json_raw_object
483
- {
484
- JSON.create_id => self.class.name,
485
- 'raw' => self.unpack('C*'),
486
- }
487
- end
488
-
489
- # This method creates a JSON text from the result of
490
- # a call to to_json_raw_object of this String.
491
- def to_json_raw(*args)
492
- to_json_raw_object.to_json(*args)
493
- end
494
- end
495
-
496
- module TrueClass
497
- # Returns a JSON string for true: 'true'.
498
- def to_json(*) 'true' end
499
- end
500
-
501
- module FalseClass
502
- # Returns a JSON string for false: 'false'.
503
- def to_json(*) 'false' end
504
- end
505
-
506
- module NilClass
507
- # Returns a JSON string for nil: 'null'.
508
- def to_json(*) 'null' end
509
- end
510
- end
511
- end
512
- end
513
- end