json 2.7.2 → 2.9.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.
data/lib/json/common.rb CHANGED
@@ -1,4 +1,5 @@
1
- #frozen_string_literal: false
1
+ # frozen_string_literal: true
2
+
2
3
  require 'json/version'
3
4
 
4
5
  module JSON
@@ -20,16 +21,19 @@ module JSON
20
21
  # ruby = [0, 1, nil]
21
22
  # JSON[ruby] # => '[0,1,null]'
22
23
  def [](object, opts = {})
23
- if object.respond_to? :to_str
24
- JSON.parse(object.to_str, opts)
25
- else
26
- JSON.generate(object, opts)
24
+ if object.is_a?(String)
25
+ return JSON.parse(object, opts)
26
+ elsif object.respond_to?(:to_str)
27
+ str = object.to_str
28
+ if str.is_a?(String)
29
+ return JSON.parse(str, opts)
30
+ end
27
31
  end
32
+
33
+ JSON.generate(object, opts)
28
34
  end
29
35
 
30
- # Returns the JSON parser class that is used by JSON. This is either
31
- # JSON::Ext::Parser or JSON::Pure::Parser:
32
- # JSON.parser # => JSON::Ext::Parser
36
+ # Returns the JSON parser class that is used by JSON.
33
37
  attr_reader :parser
34
38
 
35
39
  # Set the JSON parser class _parser_ to be used by JSON.
@@ -44,18 +48,9 @@ module JSON
44
48
  # level (absolute namespace path?). If there doesn't exist a constant at
45
49
  # the given path, an ArgumentError is raised.
46
50
  def deep_const_get(path) # :nodoc:
47
- path.to_s.split(/::/).inject(Object) do |p, c|
48
- case
49
- when c.empty? then p
50
- when p.const_defined?(c, true) then p.const_get(c)
51
- else
52
- begin
53
- p.const_missing(c)
54
- rescue NameError => e
55
- raise ArgumentError, "can't get const #{path}: #{e}"
56
- end
57
- end
58
- end
51
+ Object.const_get(path)
52
+ rescue NameError => e
53
+ raise ArgumentError, "can't get const #{path}: #{e}"
59
54
  end
60
55
 
61
56
  # Set the module _generator_ to be used by JSON.
@@ -64,7 +59,7 @@ module JSON
64
59
  @generator = generator
65
60
  generator_methods = generator::GeneratorMethods
66
61
  for const in generator_methods.constants
67
- klass = deep_const_get(const)
62
+ klass = const_get(const)
68
63
  modul = generator_methods.const_get(const)
69
64
  klass.class_eval do
70
65
  instance_methods(false).each do |m|
@@ -101,34 +96,24 @@ module JSON
101
96
  )
102
97
  end
103
98
 
104
- # Returns the JSON generator module that is used by JSON. This is
105
- # either JSON::Ext::Generator or JSON::Pure::Generator:
106
- # JSON.generator # => JSON::Ext::Generator
99
+ # Returns the JSON generator module that is used by JSON.
107
100
  attr_reader :generator
108
101
 
109
- # Sets or Returns the JSON generator state class that is used by JSON. This is
110
- # either JSON::Ext::Generator::State or JSON::Pure::Generator::State:
111
- # JSON.state # => JSON::Ext::Generator::State
102
+ # Sets or Returns the JSON generator state class that is used by JSON.
112
103
  attr_accessor :state
113
104
  end
114
105
 
115
- DEFAULT_CREATE_ID = 'json_class'.freeze
116
- private_constant :DEFAULT_CREATE_ID
117
-
118
- CREATE_ID_TLS_KEY = "JSON.create_id".freeze
119
- private_constant :CREATE_ID_TLS_KEY
120
-
121
106
  # Sets create identifier, which is used to decide if the _json_create_
122
107
  # hook of a class should be called; initial value is +json_class+:
123
108
  # JSON.create_id # => 'json_class'
124
109
  def self.create_id=(new_value)
125
- Thread.current[CREATE_ID_TLS_KEY] = new_value.dup.freeze
110
+ Thread.current[:"JSON.create_id"] = new_value.dup.freeze
126
111
  end
127
112
 
128
113
  # Returns the current create identifier.
129
114
  # See also JSON.create_id=.
130
115
  def self.create_id
131
- Thread.current[CREATE_ID_TLS_KEY] || DEFAULT_CREATE_ID
116
+ Thread.current[:"JSON.create_id"] || 'json_class'
132
117
  end
133
118
 
134
119
  NaN = 0.0/0
@@ -158,7 +143,23 @@ module JSON
158
143
  # :startdoc:
159
144
 
160
145
  # This exception is raised if a generator or unparser error occurs.
161
- class GeneratorError < JSONError; end
146
+ class GeneratorError < JSONError
147
+ attr_reader :invalid_object
148
+
149
+ def initialize(message, invalid_object = nil)
150
+ super(message)
151
+ @invalid_object = invalid_object
152
+ end
153
+
154
+ def detailed_message(...)
155
+ if @invalid_object.nil?
156
+ super
157
+ else
158
+ "#{super}\nInvalid object: #{@invalid_object.inspect}"
159
+ end
160
+ end
161
+ end
162
+
162
163
  # For backwards compatibility
163
164
  UnparserError = GeneratorError # :nodoc:
164
165
 
@@ -196,17 +197,17 @@ module JSON
196
197
  # {Parsing \JSON}[#module-JSON-label-Parsing+JSON].
197
198
  #
198
199
  # Parses nested JSON objects:
199
- # source = <<-EOT
200
- # {
201
- # "name": "Dave",
202
- # "age" :40,
203
- # "hats": [
204
- # "Cattleman's",
205
- # "Panama",
206
- # "Tophat"
207
- # ]
208
- # }
209
- # EOT
200
+ # source = <<~JSON
201
+ # {
202
+ # "name": "Dave",
203
+ # "age" :40,
204
+ # "hats": [
205
+ # "Cattleman's",
206
+ # "Panama",
207
+ # "Tophat"
208
+ # ]
209
+ # }
210
+ # JSON
210
211
  # ruby = JSON.parse(source)
211
212
  # ruby # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
212
213
  #
@@ -216,8 +217,8 @@ module JSON
216
217
  # # Raises JSON::ParserError (783: unexpected token at ''):
217
218
  # JSON.parse('')
218
219
  #
219
- def parse(source, opts = {})
220
- Parser.new(source, **(opts||{})).parse
220
+ def parse(source, opts = nil)
221
+ Parser.parse(source, opts)
221
222
  end
222
223
 
223
224
  # :call-seq:
@@ -246,8 +247,8 @@ module JSON
246
247
  # parse(File.read(path), opts)
247
248
  #
248
249
  # See method #parse.
249
- def load_file(filespec, opts = {})
250
- parse(File.read(filespec), opts)
250
+ def load_file(filespec, opts = nil)
251
+ parse(File.read(filespec, encoding: Encoding::UTF_8), opts)
251
252
  end
252
253
 
253
254
  # :call-seq:
@@ -258,7 +259,7 @@ module JSON
258
259
  #
259
260
  # See method #parse!
260
261
  def load_file!(filespec, opts = {})
261
- parse!(File.read(filespec), opts)
262
+ parse!(File.read(filespec, encoding: Encoding::UTF_8), opts)
262
263
  end
263
264
 
264
265
  # :call-seq:
@@ -299,11 +300,10 @@ module JSON
299
300
  #
300
301
  def generate(obj, opts = nil)
301
302
  if State === opts
302
- state = opts
303
+ opts.generate(obj)
303
304
  else
304
- state = State.new(opts)
305
+ State.generate(obj, opts, nil)
305
306
  end
306
- state.generate(obj)
307
307
  end
308
308
 
309
309
  # :stopdoc:
@@ -396,6 +396,20 @@ module JSON
396
396
  module_function :pretty_unparse
397
397
  # :startdoc:
398
398
 
399
+ class << self
400
+ # Sets or returns default options for the JSON.unsafe_load method.
401
+ # Initially:
402
+ # opts = JSON.load_default_options
403
+ # opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true}
404
+ attr_accessor :unsafe_load_default_options
405
+ end
406
+ self.unsafe_load_default_options = {
407
+ :max_nesting => false,
408
+ :allow_nan => true,
409
+ :allow_blank => true,
410
+ :create_additions => true,
411
+ }
412
+
399
413
  class << self
400
414
  # Sets or returns default options for the JSON.load method.
401
415
  # Initially:
@@ -404,17 +418,179 @@ module JSON
404
418
  attr_accessor :load_default_options
405
419
  end
406
420
  self.load_default_options = {
407
- :max_nesting => false,
408
421
  :allow_nan => true,
409
- :allow_blank => true,
410
- :create_additions => true,
422
+ :allow_blank => true,
423
+ :create_additions => nil,
411
424
  }
425
+ # :call-seq:
426
+ # JSON.unsafe_load(source, proc = nil, options = {}) -> object
427
+ #
428
+ # Returns the Ruby objects created by parsing the given +source+.
429
+ #
430
+ # BEWARE: This method is meant to serialise data from trusted user input,
431
+ # like from your own database server or clients under your control, it could
432
+ # be dangerous to allow untrusted users to pass JSON sources into it.
433
+ #
434
+ # - Argument +source+ must be, or be convertible to, a \String:
435
+ # - If +source+ responds to instance method +to_str+,
436
+ # <tt>source.to_str</tt> becomes the source.
437
+ # - If +source+ responds to instance method +to_io+,
438
+ # <tt>source.to_io.read</tt> becomes the source.
439
+ # - If +source+ responds to instance method +read+,
440
+ # <tt>source.read</tt> becomes the source.
441
+ # - If both of the following are true, source becomes the \String <tt>'null'</tt>:
442
+ # - Option +allow_blank+ specifies a truthy value.
443
+ # - The source, as defined above, is +nil+ or the empty \String <tt>''</tt>.
444
+ # - Otherwise, +source+ remains the source.
445
+ # - Argument +proc+, if given, must be a \Proc that accepts one argument.
446
+ # It will be called recursively with each result (depth-first order).
447
+ # See details below.
448
+ # - Argument +opts+, if given, contains a \Hash of options for the parsing.
449
+ # See {Parsing Options}[#module-JSON-label-Parsing+Options].
450
+ # The default options can be changed via method JSON.unsafe_load_default_options=.
451
+ #
452
+ # ---
453
+ #
454
+ # When no +proc+ is given, modifies +source+ as above and returns the result of
455
+ # <tt>parse(source, opts)</tt>; see #parse.
456
+ #
457
+ # Source for following examples:
458
+ # source = <<~JSON
459
+ # {
460
+ # "name": "Dave",
461
+ # "age" :40,
462
+ # "hats": [
463
+ # "Cattleman's",
464
+ # "Panama",
465
+ # "Tophat"
466
+ # ]
467
+ # }
468
+ # JSON
469
+ #
470
+ # Load a \String:
471
+ # ruby = JSON.unsafe_load(source)
472
+ # ruby # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
473
+ #
474
+ # Load an \IO object:
475
+ # require 'stringio'
476
+ # object = JSON.unsafe_load(StringIO.new(source))
477
+ # object # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
478
+ #
479
+ # Load a \File object:
480
+ # path = 't.json'
481
+ # File.write(path, source)
482
+ # File.open(path) do |file|
483
+ # JSON.unsafe_load(file)
484
+ # end # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
485
+ #
486
+ # ---
487
+ #
488
+ # When +proc+ is given:
489
+ # - Modifies +source+ as above.
490
+ # - Gets the +result+ from calling <tt>parse(source, opts)</tt>.
491
+ # - Recursively calls <tt>proc(result)</tt>.
492
+ # - Returns the final result.
493
+ #
494
+ # Example:
495
+ # require 'json'
496
+ #
497
+ # # Some classes for the example.
498
+ # class Base
499
+ # def initialize(attributes)
500
+ # @attributes = attributes
501
+ # end
502
+ # end
503
+ # class User < Base; end
504
+ # class Account < Base; end
505
+ # class Admin < Base; end
506
+ # # The JSON source.
507
+ # json = <<-EOF
508
+ # {
509
+ # "users": [
510
+ # {"type": "User", "username": "jane", "email": "jane@example.com"},
511
+ # {"type": "User", "username": "john", "email": "john@example.com"}
512
+ # ],
513
+ # "accounts": [
514
+ # {"account": {"type": "Account", "paid": true, "account_id": "1234"}},
515
+ # {"account": {"type": "Account", "paid": false, "account_id": "1235"}}
516
+ # ],
517
+ # "admins": {"type": "Admin", "password": "0wn3d"}
518
+ # }
519
+ # EOF
520
+ # # Deserializer method.
521
+ # def deserialize_obj(obj, safe_types = %w(User Account Admin))
522
+ # type = obj.is_a?(Hash) && obj["type"]
523
+ # safe_types.include?(type) ? Object.const_get(type).new(obj) : obj
524
+ # end
525
+ # # Call to JSON.unsafe_load
526
+ # ruby = JSON.unsafe_load(json, proc {|obj|
527
+ # case obj
528
+ # when Hash
529
+ # obj.each {|k, v| obj[k] = deserialize_obj v }
530
+ # when Array
531
+ # obj.map! {|v| deserialize_obj v }
532
+ # end
533
+ # })
534
+ # pp ruby
535
+ # Output:
536
+ # {"users"=>
537
+ # [#<User:0x00000000064c4c98
538
+ # @attributes=
539
+ # {"type"=>"User", "username"=>"jane", "email"=>"jane@example.com"}>,
540
+ # #<User:0x00000000064c4bd0
541
+ # @attributes=
542
+ # {"type"=>"User", "username"=>"john", "email"=>"john@example.com"}>],
543
+ # "accounts"=>
544
+ # [{"account"=>
545
+ # #<Account:0x00000000064c4928
546
+ # @attributes={"type"=>"Account", "paid"=>true, "account_id"=>"1234"}>},
547
+ # {"account"=>
548
+ # #<Account:0x00000000064c4680
549
+ # @attributes={"type"=>"Account", "paid"=>false, "account_id"=>"1235"}>}],
550
+ # "admins"=>
551
+ # #<Admin:0x00000000064c41f8
552
+ # @attributes={"type"=>"Admin", "password"=>"0wn3d"}>}
553
+ #
554
+ def unsafe_load(source, proc = nil, options = nil)
555
+ opts = if options.nil?
556
+ unsafe_load_default_options
557
+ else
558
+ unsafe_load_default_options.merge(options)
559
+ end
560
+
561
+ unless source.is_a?(String)
562
+ if source.respond_to? :to_str
563
+ source = source.to_str
564
+ elsif source.respond_to? :to_io
565
+ source = source.to_io.read
566
+ elsif source.respond_to?(:read)
567
+ source = source.read
568
+ end
569
+ end
570
+
571
+ if opts[:allow_blank] && (source.nil? || source.empty?)
572
+ source = 'null'
573
+ end
574
+ result = parse(source, opts)
575
+ recurse_proc(result, &proc) if proc
576
+ result
577
+ end
412
578
 
413
579
  # :call-seq:
414
580
  # JSON.load(source, proc = nil, options = {}) -> object
415
581
  #
416
582
  # Returns the Ruby objects created by parsing the given +source+.
417
583
  #
584
+ # BEWARE: This method is meant to serialise data from trusted user input,
585
+ # like from your own database server or clients under your control, it could
586
+ # be dangerous to allow untrusted users to pass JSON sources into it.
587
+ # If you must use it, use JSON.unsafe_load instead to make it clear.
588
+ #
589
+ # Since JSON version 2.8.0, `load` emits a deprecation warning when a
590
+ # non native type is deserialized, without `create_additions` being explicitly
591
+ # enabled, and in JSON version 3.0, `load` will have `create_additions` disabled
592
+ # by default.
593
+ #
418
594
  # - Argument +source+ must be, or be convertible to, a \String:
419
595
  # - If +source+ responds to instance method +to_str+,
420
596
  # <tt>source.to_str</tt> becomes the source.
@@ -429,9 +605,6 @@ module JSON
429
605
  # - Argument +proc+, if given, must be a \Proc that accepts one argument.
430
606
  # It will be called recursively with each result (depth-first order).
431
607
  # See details below.
432
- # BEWARE: This method is meant to serialise data from trusted user input,
433
- # like from your own database server or clients under your control, it could
434
- # be dangerous to allow untrusted users to pass JSON sources into it.
435
608
  # - Argument +opts+, if given, contains a \Hash of options for the parsing.
436
609
  # See {Parsing Options}[#module-JSON-label-Parsing+Options].
437
610
  # The default options can be changed via method JSON.load_default_options=.
@@ -442,17 +615,17 @@ module JSON
442
615
  # <tt>parse(source, opts)</tt>; see #parse.
443
616
  #
444
617
  # Source for following examples:
445
- # source = <<-EOT
446
- # {
447
- # "name": "Dave",
448
- # "age" :40,
449
- # "hats": [
450
- # "Cattleman's",
451
- # "Panama",
452
- # "Tophat"
453
- # ]
454
- # }
455
- # EOT
618
+ # source = <<~JSON
619
+ # {
620
+ # "name": "Dave",
621
+ # "age" :40,
622
+ # "hats": [
623
+ # "Cattleman's",
624
+ # "Panama",
625
+ # "Tophat"
626
+ # ]
627
+ # }
628
+ # JSON
456
629
  #
457
630
  # Load a \String:
458
631
  # ruby = JSON.load(source)
@@ -538,15 +711,23 @@ module JSON
538
711
  # #<Admin:0x00000000064c41f8
539
712
  # @attributes={"type"=>"Admin", "password"=>"0wn3d"}>}
540
713
  #
541
- def load(source, proc = nil, options = {})
542
- opts = load_default_options.merge options
543
- if source.respond_to? :to_str
544
- source = source.to_str
545
- elsif source.respond_to? :to_io
546
- source = source.to_io.read
547
- elsif source.respond_to?(:read)
548
- source = source.read
714
+ def load(source, proc = nil, options = nil)
715
+ opts = if options.nil?
716
+ load_default_options
717
+ else
718
+ load_default_options.merge(options)
549
719
  end
720
+
721
+ unless source.is_a?(String)
722
+ if source.respond_to? :to_str
723
+ source = source.to_str
724
+ elsif source.respond_to? :to_io
725
+ source = source.to_io.read
726
+ elsif source.respond_to?(:read)
727
+ source = source.read
728
+ end
729
+ end
730
+
550
731
  if opts[:allow_blank] && (source.nil? || source.empty?)
551
732
  source = 'null'
552
733
  end
@@ -576,13 +757,12 @@ module JSON
576
757
  # Sets or returns the default options for the JSON.dump method.
577
758
  # Initially:
578
759
  # opts = JSON.dump_default_options
579
- # opts # => {:max_nesting=>false, :allow_nan=>true, :script_safe=>false}
760
+ # opts # => {:max_nesting=>false, :allow_nan=>true}
580
761
  attr_accessor :dump_default_options
581
762
  end
582
763
  self.dump_default_options = {
583
764
  :max_nesting => false,
584
765
  :allow_nan => true,
585
- :script_safe => false,
586
766
  }
587
767
 
588
768
  # :call-seq:
@@ -613,26 +793,39 @@ module JSON
613
793
  # Output:
614
794
  # {"foo":[0,1],"bar":{"baz":2,"bat":3},"bam":"bad"}
615
795
  def dump(obj, anIO = nil, limit = nil, kwargs = nil)
616
- io_limit_opt = [anIO, limit, kwargs].compact
617
- kwargs = io_limit_opt.pop if io_limit_opt.last.is_a?(Hash)
618
- anIO, limit = io_limit_opt
619
- if anIO.respond_to?(:to_io)
620
- anIO = anIO.to_io
621
- elsif limit.nil? && !anIO.respond_to?(:write)
622
- anIO, limit = nil, anIO
796
+ if kwargs.nil?
797
+ if limit.nil?
798
+ if anIO.is_a?(Hash)
799
+ kwargs = anIO
800
+ anIO = nil
801
+ end
802
+ elsif limit.is_a?(Hash)
803
+ kwargs = limit
804
+ limit = nil
805
+ end
623
806
  end
807
+
808
+ unless anIO.nil?
809
+ if anIO.respond_to?(:to_io)
810
+ anIO = anIO.to_io
811
+ elsif limit.nil? && !anIO.respond_to?(:write)
812
+ anIO, limit = nil, anIO
813
+ end
814
+ end
815
+
624
816
  opts = JSON.dump_default_options
625
817
  opts = opts.merge(:max_nesting => limit) if limit
626
818
  opts = merge_dump_options(opts, **kwargs) if kwargs
627
- result = generate(obj, opts)
628
- if anIO
629
- anIO.write result
630
- anIO
631
- else
632
- result
819
+
820
+ begin
821
+ if State === opts
822
+ opts.generate(obj, anIO)
823
+ else
824
+ State.generate(obj, opts, anIO)
825
+ end
826
+ rescue JSON::NestingError
827
+ raise ArgumentError, "exceed depth limit"
633
828
  end
634
- rescue JSON::NestingError
635
- raise ArgumentError, "exceed depth limit"
636
829
  end
637
830
 
638
831
  # Encodes string using String.encode.
@@ -678,11 +871,16 @@ module ::Kernel
678
871
  # The _opts_ argument is passed through to generate/parse respectively. See
679
872
  # generate and parse for their documentation.
680
873
  def JSON(object, *args)
681
- if object.respond_to? :to_str
682
- JSON.parse(object.to_str, args.first)
683
- else
684
- JSON.generate(object, args.first)
874
+ if object.is_a?(String)
875
+ return JSON.parse(object, args.first)
876
+ elsif object.respond_to?(:to_str)
877
+ str = object.to_str
878
+ if str.is_a?(String)
879
+ return JSON.parse(object.to_str, args.first)
880
+ end
685
881
  end
882
+
883
+ JSON.generate(object, args.first)
686
884
  end
687
885
  end
688
886
 
@@ -0,0 +1,116 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JSON
4
+ module Ext
5
+ module Generator
6
+ class State
7
+ # call-seq: new(opts = {})
8
+ #
9
+ # Instantiates a new State object, configured by _opts_.
10
+ #
11
+ # _opts_ can have the following keys:
12
+ #
13
+ # * *indent*: a string used to indent levels (default: ''),
14
+ # * *space*: a string that is put after, a : or , delimiter (default: ''),
15
+ # * *space_before*: a string that is put before a : pair delimiter (default: ''),
16
+ # * *object_nl*: a string that is put at the end of a JSON object (default: ''),
17
+ # * *array_nl*: a string that is put at the end of a JSON array (default: ''),
18
+ # * *allow_nan*: true if NaN, Infinity, and -Infinity should be
19
+ # generated, otherwise an exception is thrown, if these values are
20
+ # encountered. This options defaults to false.
21
+ # * *ascii_only*: true if only ASCII characters should be generated. This
22
+ # option defaults to false.
23
+ # * *buffer_initial_length*: sets the initial length of the generator's
24
+ # internal buffer.
25
+ def initialize(opts = nil)
26
+ if opts && !opts.empty?
27
+ configure(opts)
28
+ end
29
+ end
30
+
31
+ # call-seq: configure(opts)
32
+ #
33
+ # Configure this State instance with the Hash _opts_, and return
34
+ # itself.
35
+ def configure(opts)
36
+ unless opts.is_a?(Hash)
37
+ if opts.respond_to?(:to_hash)
38
+ opts = opts.to_hash
39
+ elsif opts.respond_to?(:to_h)
40
+ opts = opts.to_h
41
+ else
42
+ raise TypeError, "can't convert #{opts.class} into Hash"
43
+ end
44
+ end
45
+ _configure(opts)
46
+ end
47
+
48
+ alias_method :merge, :configure
49
+
50
+ # call-seq:
51
+ # generate(obj) -> String
52
+ # generate(obj, anIO) -> anIO
53
+ #
54
+ # Generates a valid JSON document from object +obj+ and returns the
55
+ # result. If no valid JSON document can be created this method raises a
56
+ # GeneratorError exception.
57
+ def generate(obj, io = nil)
58
+ _generate(obj, io)
59
+ end
60
+
61
+ # call-seq: to_h
62
+ #
63
+ # Returns the configuration instance variables as a hash, that can be
64
+ # passed to the configure method.
65
+ def to_h
66
+ result = {
67
+ indent: indent,
68
+ space: space,
69
+ space_before: space_before,
70
+ object_nl: object_nl,
71
+ array_nl: array_nl,
72
+ allow_nan: allow_nan?,
73
+ ascii_only: ascii_only?,
74
+ max_nesting: max_nesting,
75
+ script_safe: script_safe?,
76
+ strict: strict?,
77
+ depth: depth,
78
+ buffer_initial_length: buffer_initial_length,
79
+ }
80
+
81
+ instance_variables.each do |iv|
82
+ iv = iv.to_s[1..-1]
83
+ result[iv.to_sym] = self[iv]
84
+ end
85
+
86
+ result
87
+ end
88
+
89
+ alias_method :to_hash, :to_h
90
+
91
+ # call-seq: [](name)
92
+ #
93
+ # Returns the value returned by method +name+.
94
+ def [](name)
95
+ if respond_to?(name)
96
+ __send__(name)
97
+ else
98
+ instance_variable_get("@#{name}") if
99
+ instance_variables.include?("@#{name}".to_sym) # avoid warning
100
+ end
101
+ end
102
+
103
+ # call-seq: []=(name, value)
104
+ #
105
+ # Sets the attribute name to value.
106
+ def []=(name, value)
107
+ if respond_to?(name_writer = "#{name}=")
108
+ __send__ name_writer, value
109
+ else
110
+ instance_variable_set "@#{name}", value
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end