json 2.6.2 → 2.7.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,14 +5,29 @@ end
5
5
 
6
6
  class Range
7
7
 
8
- # Deserializes JSON string by constructing new Range object with arguments
9
- # <tt>a</tt> serialized by <tt>to_json</tt>.
8
+ # See #as_json.
10
9
  def self.json_create(object)
11
10
  new(*object['a'])
12
11
  end
13
12
 
14
- # Returns a hash, that will be turned into a JSON object and represent this
15
- # object.
13
+ # Methods <tt>Range#as_json</tt> and +Range.json_create+ may be used
14
+ # to serialize and deserialize a \Range object;
15
+ # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
16
+ #
17
+ # \Method <tt>Range#as_json</tt> serializes +self+,
18
+ # returning a 2-element hash representing +self+:
19
+ #
20
+ # require 'json/add/range'
21
+ # x = (1..4).as_json # => {"json_class"=>"Range", "a"=>[1, 4, false]}
22
+ # y = (1...4).as_json # => {"json_class"=>"Range", "a"=>[1, 4, true]}
23
+ # z = ('a'..'d').as_json # => {"json_class"=>"Range", "a"=>["a", "d", false]}
24
+ #
25
+ # \Method +JSON.create+ deserializes such a hash, returning a \Range object:
26
+ #
27
+ # Range.json_create(x) # => 1..4
28
+ # Range.json_create(y) # => 1...4
29
+ # Range.json_create(z) # => "a".."d"
30
+ #
16
31
  def as_json(*)
17
32
  {
18
33
  JSON.create_id => self.class.name,
@@ -20,9 +35,19 @@ class Range
20
35
  }
21
36
  end
22
37
 
23
- # Stores class name (Range) with JSON array of arguments <tt>a</tt> which
24
- # include <tt>first</tt> (integer), <tt>last</tt> (integer), and
25
- # <tt>exclude_end?</tt> (boolean) as JSON string.
38
+ # Returns a JSON string representing +self+:
39
+ #
40
+ # require 'json/add/range'
41
+ # puts (1..4).to_json
42
+ # puts (1...4).to_json
43
+ # puts ('a'..'d').to_json
44
+ #
45
+ # Output:
46
+ #
47
+ # {"json_class":"Range","a":[1,4,false]}
48
+ # {"json_class":"Range","a":[1,4,true]}
49
+ # {"json_class":"Range","a":["a","d",false]}
50
+ #
26
51
  def to_json(*args)
27
52
  as_json.to_json(*args)
28
53
  end
@@ -4,14 +4,28 @@ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
4
4
  end
5
5
 
6
6
  class Rational
7
- # Deserializes JSON string by converting numerator value <tt>n</tt>,
8
- # denominator value <tt>d</tt>, to a Rational object.
7
+
8
+ # See #as_json.
9
9
  def self.json_create(object)
10
10
  Rational(object['n'], object['d'])
11
11
  end
12
12
 
13
- # Returns a hash, that will be turned into a JSON object and represent this
14
- # object.
13
+ # Methods <tt>Rational#as_json</tt> and +Rational.json_create+ may be used
14
+ # to serialize and deserialize a \Rational object;
15
+ # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
16
+ #
17
+ # \Method <tt>Rational#as_json</tt> serializes +self+,
18
+ # returning a 2-element hash representing +self+:
19
+ #
20
+ # require 'json/add/rational'
21
+ # x = Rational(2, 3).as_json
22
+ # # => {"json_class"=>"Rational", "n"=>2, "d"=>3}
23
+ #
24
+ # \Method +JSON.create+ deserializes such a hash, returning a \Rational object:
25
+ #
26
+ # Rational.json_create(x)
27
+ # # => (2/3)
28
+ #
15
29
  def as_json(*)
16
30
  {
17
31
  JSON.create_id => self.class.name,
@@ -20,7 +34,15 @@ class Rational
20
34
  }
21
35
  end
22
36
 
23
- # Stores class name (Rational) along with numerator value <tt>n</tt> and denominator value <tt>d</tt> as JSON string
37
+ # Returns a JSON string representing +self+:
38
+ #
39
+ # require 'json/add/rational'
40
+ # puts Rational(2, 3).to_json
41
+ #
42
+ # Output:
43
+ #
44
+ # {"json_class":"Rational","n":2,"d":3}
45
+ #
24
46
  def to_json(*args)
25
47
  as_json.to_json(*args)
26
48
  end
@@ -5,15 +5,26 @@ end
5
5
 
6
6
  class Regexp
7
7
 
8
- # Deserializes JSON string by constructing new Regexp object with source
9
- # <tt>s</tt> (Regexp or String) and options <tt>o</tt> serialized by
10
- # <tt>to_json</tt>
8
+ # See #as_json.
11
9
  def self.json_create(object)
12
10
  new(object['s'], object['o'])
13
11
  end
14
12
 
15
- # Returns a hash, that will be turned into a JSON object and represent this
16
- # object.
13
+ # Methods <tt>Regexp#as_json</tt> and +Regexp.json_create+ may be used
14
+ # to serialize and deserialize a \Regexp object;
15
+ # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
16
+ #
17
+ # \Method <tt>Regexp#as_json</tt> serializes +self+,
18
+ # returning a 2-element hash representing +self+:
19
+ #
20
+ # require 'json/add/regexp'
21
+ # x = /foo/.as_json
22
+ # # => {"json_class"=>"Regexp", "o"=>0, "s"=>"foo"}
23
+ #
24
+ # \Method +JSON.create+ deserializes such a hash, returning a \Regexp object:
25
+ #
26
+ # Regexp.json_create(x) # => /foo/
27
+ #
17
28
  def as_json(*)
18
29
  {
19
30
  JSON.create_id => self.class.name,
@@ -22,8 +33,15 @@ class Regexp
22
33
  }
23
34
  end
24
35
 
25
- # Stores class name (Regexp) with options <tt>o</tt> and source <tt>s</tt>
26
- # (Regexp or String) as JSON string
36
+ # Returns a JSON string representing +self+:
37
+ #
38
+ # require 'json/add/regexp'
39
+ # puts /foo/.to_json
40
+ #
41
+ # Output:
42
+ #
43
+ # {"json_class":"Regexp","o":0,"s":"foo"}
44
+ #
27
45
  def to_json(*args)
28
46
  as_json.to_json(*args)
29
47
  end
data/lib/json/add/set.rb CHANGED
@@ -4,16 +4,27 @@ end
4
4
  defined?(::Set) or require 'set'
5
5
 
6
6
  class Set
7
- # Import a JSON Marshalled object.
8
- #
9
- # method used for JSON marshalling support.
7
+
8
+ # See #as_json.
10
9
  def self.json_create(object)
11
10
  new object['a']
12
11
  end
13
12
 
14
- # Marshal the object to JSON.
13
+ # Methods <tt>Set#as_json</tt> and +Set.json_create+ may be used
14
+ # to serialize and deserialize a \Set object;
15
+ # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
16
+ #
17
+ # \Method <tt>Set#as_json</tt> serializes +self+,
18
+ # returning a 2-element hash representing +self+:
19
+ #
20
+ # require 'json/add/set'
21
+ # x = Set.new(%w/foo bar baz/).as_json
22
+ # # => {"json_class"=>"Set", "a"=>["foo", "bar", "baz"]}
23
+ #
24
+ # \Method +JSON.create+ deserializes such a hash, returning a \Set object:
25
+ #
26
+ # Set.json_create(x) # => #<Set: {"foo", "bar", "baz"}>
15
27
  #
16
- # method used for JSON marshalling support.
17
28
  def as_json(*)
18
29
  {
19
30
  JSON.create_id => self.class.name,
@@ -21,7 +32,15 @@ class Set
21
32
  }
22
33
  end
23
34
 
24
- # return the JSON value
35
+ # Returns a JSON string representing +self+:
36
+ #
37
+ # require 'json/add/set'
38
+ # puts Set.new(%w/foo bar baz/).to_json
39
+ #
40
+ # Output:
41
+ #
42
+ # {"json_class":"Set","a":["foo","bar","baz"]}
43
+ #
25
44
  def to_json(*args)
26
45
  as_json.to_json(*args)
27
46
  end
@@ -5,14 +5,28 @@ end
5
5
 
6
6
  class Struct
7
7
 
8
- # Deserializes JSON string by constructing new Struct object with values
9
- # <tt>v</tt> serialized by <tt>to_json</tt>.
8
+ # See #as_json.
10
9
  def self.json_create(object)
11
10
  new(*object['v'])
12
11
  end
13
12
 
14
- # Returns a hash, that will be turned into a JSON object and represent this
15
- # object.
13
+ # Methods <tt>Struct#as_json</tt> and +Struct.json_create+ may be used
14
+ # to serialize and deserialize a \Struct object;
15
+ # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
16
+ #
17
+ # \Method <tt>Struct#as_json</tt> serializes +self+,
18
+ # returning a 2-element hash representing +self+:
19
+ #
20
+ # require 'json/add/struct'
21
+ # Customer = Struct.new('Customer', :name, :address, :zip)
22
+ # x = Struct::Customer.new.as_json
23
+ # # => {"json_class"=>"Struct::Customer", "v"=>[nil, nil, nil]}
24
+ #
25
+ # \Method +JSON.create+ deserializes such a hash, returning a \Struct object:
26
+ #
27
+ # Struct::Customer.json_create(x)
28
+ # # => #<struct Struct::Customer name=nil, address=nil, zip=nil>
29
+ #
16
30
  def as_json(*)
17
31
  klass = self.class.name
18
32
  klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!"
@@ -22,8 +36,16 @@ class Struct
22
36
  }
23
37
  end
24
38
 
25
- # Stores class name (Struct) with Struct values <tt>v</tt> as a JSON string.
26
- # Only named structs are supported.
39
+ # Returns a JSON string representing +self+:
40
+ #
41
+ # require 'json/add/struct'
42
+ # Customer = Struct.new('Customer', :name, :address, :zip)
43
+ # puts Struct::Customer.new.to_json
44
+ #
45
+ # Output:
46
+ #
47
+ # {"json_class":"Struct","t":{'name':'Rowdy',"age":null}}
48
+ #
27
49
  def to_json(*args)
28
50
  as_json.to_json(*args)
29
51
  end
@@ -1,11 +1,26 @@
1
+
1
2
  #frozen_string_literal: false
2
3
  unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
3
4
  require 'json'
4
5
  end
5
6
 
6
7
  class Symbol
7
- # Returns a hash, that will be turned into a JSON object and represent this
8
- # object.
8
+
9
+ # Methods <tt>Symbol#as_json</tt> and +Symbol.json_create+ may be used
10
+ # to serialize and deserialize a \Symbol object;
11
+ # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
12
+ #
13
+ # \Method <tt>Symbol#as_json</tt> serializes +self+,
14
+ # returning a 2-element hash representing +self+:
15
+ #
16
+ # require 'json/add/symbol'
17
+ # x = :foo.as_json
18
+ # # => {"json_class"=>"Symbol", "s"=>"foo"}
19
+ #
20
+ # \Method +JSON.create+ deserializes such a hash, returning a \Symbol object:
21
+ #
22
+ # Symbol.json_create(x) # => :foo
23
+ #
9
24
  def as_json(*)
10
25
  {
11
26
  JSON.create_id => self.class.name,
@@ -13,12 +28,20 @@ class Symbol
13
28
  }
14
29
  end
15
30
 
16
- # Stores class name (Symbol) with String representation of Symbol as a JSON string.
31
+ # Returns a JSON string representing +self+:
32
+ #
33
+ # require 'json/add/symbol'
34
+ # puts :foo.to_json
35
+ #
36
+ # Output:
37
+ #
38
+ # # {"json_class":"Symbol","s":"foo"}
39
+ #
17
40
  def to_json(*a)
18
41
  as_json.to_json(*a)
19
42
  end
20
43
 
21
- # Deserializes JSON string by converting the <tt>string</tt> value stored in the object to a Symbol
44
+ # See #as_json.
22
45
  def self.json_create(o)
23
46
  o['s'].to_sym
24
47
  end
data/lib/json/add/time.rb CHANGED
@@ -5,7 +5,7 @@ end
5
5
 
6
6
  class Time
7
7
 
8
- # Deserializes JSON string by converting time since epoch to Time
8
+ # See #as_json.
9
9
  def self.json_create(object)
10
10
  if usec = object.delete('u') # used to be tv_usec -> tv_nsec
11
11
  object['n'] = usec * 1000
@@ -17,8 +17,22 @@ class Time
17
17
  end
18
18
  end
19
19
 
20
- # Returns a hash, that will be turned into a JSON object and represent this
21
- # object.
20
+ # Methods <tt>Time#as_json</tt> and +Time.json_create+ may be used
21
+ # to serialize and deserialize a \Time object;
22
+ # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
23
+ #
24
+ # \Method <tt>Time#as_json</tt> serializes +self+,
25
+ # returning a 2-element hash representing +self+:
26
+ #
27
+ # require 'json/add/time'
28
+ # x = Time.now.as_json
29
+ # # => {"json_class"=>"Time", "s"=>1700931656, "n"=>472846644}
30
+ #
31
+ # \Method +JSON.create+ deserializes such a hash, returning a \Time object:
32
+ #
33
+ # Time.json_create(x)
34
+ # # => 2023-11-25 11:00:56.472846644 -0600
35
+ #
22
36
  def as_json(*)
23
37
  nanoseconds = [ tv_usec * 1000 ]
24
38
  respond_to?(:tv_nsec) and nanoseconds << tv_nsec
@@ -30,8 +44,15 @@ class Time
30
44
  }
31
45
  end
32
46
 
33
- # Stores class name (Time) with number of seconds since epoch and number of
34
- # microseconds for Time as JSON string
47
+ # Returns a JSON string representing +self+:
48
+ #
49
+ # require 'json/add/time'
50
+ # puts Time.now.to_json
51
+ #
52
+ # Output:
53
+ #
54
+ # {"json_class":"Time","s":1700931678,"n":980650786}
55
+ #
35
56
  def to_json(*args)
36
57
  as_json.to_json(*args)
37
58
  end
data/lib/json/common.rb CHANGED
@@ -1,8 +1,12 @@
1
1
  #frozen_string_literal: false
2
2
  require 'json/version'
3
- require 'json/generic_object'
4
3
 
5
4
  module JSON
5
+ autoload :GenericObject, 'json/generic_object'
6
+
7
+ NOT_SET = Object.new.freeze
8
+ private_constant :NOT_SET
9
+
6
10
  class << self
7
11
  # :call-seq:
8
12
  # JSON[object] -> new_array or new_string
@@ -295,19 +299,9 @@ module JSON
295
299
  #
296
300
  def generate(obj, opts = nil)
297
301
  if State === opts
298
- state, opts = opts, nil
302
+ state = opts
299
303
  else
300
- state = State.new
301
- end
302
- if opts
303
- if opts.respond_to? :to_hash
304
- opts = opts.to_hash
305
- elsif opts.respond_to? :to_h
306
- opts = opts.to_h
307
- else
308
- raise TypeError, "can't convert #{opts.class} into Hash"
309
- end
310
- state = state.configure(opts)
304
+ state = State.new(opts)
311
305
  end
312
306
  state.generate(obj)
313
307
  end
@@ -334,19 +328,9 @@ module JSON
334
328
  # JSON.fast_generate(a)
335
329
  def fast_generate(obj, opts = nil)
336
330
  if State === opts
337
- state, opts = opts, nil
331
+ state = opts
338
332
  else
339
- state = JSON.create_fast_state
340
- end
341
- if opts
342
- if opts.respond_to? :to_hash
343
- opts = opts.to_hash
344
- elsif opts.respond_to? :to_h
345
- opts = opts.to_h
346
- else
347
- raise TypeError, "can't convert #{opts.class} into Hash"
348
- end
349
- state.configure(opts)
333
+ state = JSON.create_fast_state.configure(opts)
350
334
  end
351
335
  state.generate(obj)
352
336
  end
@@ -592,13 +576,13 @@ module JSON
592
576
  # Sets or returns the default options for the JSON.dump method.
593
577
  # Initially:
594
578
  # opts = JSON.dump_default_options
595
- # opts # => {:max_nesting=>false, :allow_nan=>true, :escape_slash=>false}
579
+ # opts # => {:max_nesting=>false, :allow_nan=>true, :script_safe=>false}
596
580
  attr_accessor :dump_default_options
597
581
  end
598
582
  self.dump_default_options = {
599
583
  :max_nesting => false,
600
584
  :allow_nan => true,
601
- :escape_slash => false,
585
+ :script_safe => false,
602
586
  }
603
587
 
604
588
  # :call-seq:
@@ -628,16 +612,18 @@ module JSON
628
612
  # puts File.read(path)
629
613
  # Output:
630
614
  # {"foo":[0,1],"bar":{"baz":2,"bat":3},"bam":"bad"}
631
- def dump(obj, anIO = nil, limit = nil)
632
- if anIO and limit.nil?
633
- anIO = anIO.to_io if anIO.respond_to?(:to_io)
634
- unless anIO.respond_to?(:write)
635
- limit = anIO
636
- anIO = nil
637
- end
615
+ 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
638
623
  end
639
624
  opts = JSON.dump_default_options
640
625
  opts = opts.merge(:max_nesting => limit) if limit
626
+ opts = merge_dump_options(opts, **kwargs) if kwargs
641
627
  result = generate(obj, opts)
642
628
  if anIO
643
629
  anIO.write result
@@ -653,6 +639,15 @@ module JSON
653
639
  def self.iconv(to, from, string)
654
640
  string.encode(to, from)
655
641
  end
642
+
643
+ def merge_dump_options(opts, strict: NOT_SET)
644
+ opts = opts.merge(strict: strict) if NOT_SET != strict
645
+ opts
646
+ end
647
+
648
+ class << self
649
+ private :merge_dump_options
650
+ end
656
651
  end
657
652
 
658
653
  module ::Kernel
@@ -1,5 +1,9 @@
1
1
  #frozen_string_literal: false
2
- require 'ostruct'
2
+ begin
3
+ require 'ostruct'
4
+ rescue LoadError
5
+ warn "JSON::GenericObject requires 'ostruct'. Please install it with `gem install ostruct`."
6
+ end
3
7
 
4
8
  module JSON
5
9
  class GenericObject < OpenStruct
@@ -67,5 +71,5 @@ module JSON
67
71
  def to_json(*a)
68
72
  as_json.to_json(*a)
69
73
  end
70
- end
74
+ end if defined?(::OpenStruct)
71
75
  end