json 2.7.0 → 2.7.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 69c4723749fff4656746bdf94f5f0a580e7159f52fac2eb403ed5cd93b3c6a42
4
- data.tar.gz: 1dbf07b0f5aa76c4daace5af98486c7d1b51b599e193944385873ff385e38383
3
+ metadata.gz: 1ae811d90e98bbf8438c5abff24a9eabd5ef9c929115c14d3616a0c23f3a3fa2
4
+ data.tar.gz: eaa6afeb5ed814f5272bf54172b98ab217b26f850cb91d6fb081a9551237030c
5
5
  SHA512:
6
- metadata.gz: 5e0b326ca829e7bc720ebc211b68afcaff80606d370faccf76610ce711bd1d9c128e38ec88bdff803ee7b4f2454cfa84db4f40f719024f17c99099fd9a386485
7
- data.tar.gz: 9daaad6f0e574f80878ad50a9402c646d6b27387ef34711cc75167f3902d7e295ad3633976632ecfd90db898022973fcf3aa81f8bf48c969f2b83298f242003b
6
+ metadata.gz: c4119c5fdb66b553ee50cab0185cdec0ff7b09f102cfec8faa28efe2a6042d1e5cb46ada853afdc47b76707b5b180e0f68fb039e08e329935434716e2419b8e1
7
+ data.tar.gz: f7d69e1e729e4b37687358bd6ebf81e8909fe4418bfff5c8a2d676b070d6af979146d0b18c01820d5bd4a7f567a62cbb90d0e164e96d05c0e99d9968657467c0
data/CHANGES.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changes
2
2
 
3
+ ### 2023-12-05 (2.7.1)
4
+
5
+ * JSON.dump: handle unenclosed hashes regression #554
6
+ * Overload kwargs in JSON.dump #556
7
+ * [DOC] RDoc for additions #557
8
+ * Fix JSON.dump overload combination #558
9
+
3
10
  ### 2023-12-01 (2.7.0)
4
11
 
5
12
  * Add a strict option to Generator #519
data/README.md CHANGED
@@ -140,15 +140,6 @@ JSON JSON(1..10) # => 1..10
140
140
  To find out how to add JSON support to other or your own classes, read the
141
141
  section "More Examples" below.
142
142
 
143
- To get the best compatibility to rails' JSON implementation, you can
144
-
145
- ```ruby
146
- require 'json/add/rails'
147
- ```
148
-
149
- Both of the additions attempt to require `'json'` (like above) first, if it has
150
- not been required yet.
151
-
152
143
  ## Serializing exceptions
153
144
 
154
145
  The JSON module doesn't extend `Exception` by default. If you convert an `Exception`
@@ -867,7 +867,7 @@ json_object_i(VALUE key, VALUE val, VALUE _arg)
867
867
  if (klass == rb_cString) {
868
868
  key_to_s = key;
869
869
  } else if (klass == rb_cSymbol) {
870
- key_to_s = rb_id2str(SYM2ID(key));
870
+ key_to_s = rb_sym2str(key);
871
871
  } else {
872
872
  key_to_s = rb_funcall(key, i_to_s, 0);
873
873
  }
@@ -892,7 +892,6 @@ static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_S
892
892
  struct hash_foreach_arg arg;
893
893
 
894
894
  if (max_nesting != 0 && depth > max_nesting) {
895
- fbuffer_free(buffer);
896
895
  rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
897
896
  }
898
897
  fbuffer_append_char(buffer, '{');
@@ -927,7 +926,6 @@ static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
927
926
  long depth = ++state->depth;
928
927
  int i, j;
929
928
  if (max_nesting != 0 && depth > max_nesting) {
930
- fbuffer_free(buffer);
931
929
  rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
932
930
  }
933
931
  fbuffer_append_char(buffer, '[');
@@ -1020,10 +1018,8 @@ static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
1020
1018
  VALUE tmp = rb_funcall(obj, i_to_s, 0);
1021
1019
  if (!allow_nan) {
1022
1020
  if (isinf(value)) {
1023
- fbuffer_free(buffer);
1024
1021
  rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(tmp));
1025
1022
  } else if (isnan(value)) {
1026
- fbuffer_free(buffer);
1027
1023
  rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(tmp));
1028
1024
  }
1029
1025
  }
@@ -1096,11 +1092,45 @@ static FBuffer *cState_prepare_buffer(VALUE self)
1096
1092
  return buffer;
1097
1093
  }
1098
1094
 
1095
+ struct generate_json_data {
1096
+ FBuffer *buffer;
1097
+ VALUE vstate;
1098
+ JSON_Generator_State *state;
1099
+ VALUE obj;
1100
+ };
1101
+
1102
+ static VALUE generate_json_try(VALUE d)
1103
+ {
1104
+ struct generate_json_data *data = (struct generate_json_data *)d;
1105
+
1106
+ generate_json(data->buffer, data->vstate, data->state, data->obj);
1107
+
1108
+ return Qnil;
1109
+ }
1110
+
1111
+ static VALUE generate_json_rescue(VALUE d, VALUE exc)
1112
+ {
1113
+ struct generate_json_data *data = (struct generate_json_data *)d;
1114
+ fbuffer_free(data->buffer);
1115
+
1116
+ rb_exc_raise(exc);
1117
+
1118
+ return Qundef;
1119
+ }
1120
+
1099
1121
  static VALUE cState_partial_generate(VALUE self, VALUE obj)
1100
1122
  {
1101
1123
  FBuffer *buffer = cState_prepare_buffer(self);
1102
1124
  GET_STATE(self);
1103
- generate_json(buffer, self, state, obj);
1125
+
1126
+ struct generate_json_data data = {
1127
+ .buffer = buffer,
1128
+ .vstate = self,
1129
+ .state = state,
1130
+ .obj = obj
1131
+ };
1132
+ rb_rescue(generate_json_try, (VALUE)&data, generate_json_rescue, (VALUE)&data);
1133
+
1104
1134
  return fbuffer_to_s(buffer);
1105
1135
  }
1106
1136
 
data/json.gemspec CHANGED
@@ -1,8 +1,10 @@
1
- # -*- encoding: utf-8 -*-
1
+ version = File.foreach(File.join(__dir__, "lib/json/version.rb")) do |line|
2
+ /^\s*VERSION\s*=\s*'(.*)'/ =~ line and break $1
3
+ end rescue nil
2
4
 
3
5
  Gem::Specification.new do |s|
4
6
  s.name = "json"
5
- s.version = File.read(File.expand_path('../VERSION', __FILE__)).chomp
7
+ s.version = version
6
8
 
7
9
  s.summary = "JSON Implementation for Ruby"
8
10
  s.description = "This is a JSON implementation as a Ruby extension in C."
@@ -17,7 +19,6 @@ Gem::Specification.new do |s|
17
19
  "CHANGES.md",
18
20
  "LICENSE",
19
21
  "README.md",
20
- "VERSION",
21
22
  "ext/json/ext/fbuffer/fbuffer.h",
22
23
  "ext/json/ext/generator/depend",
23
24
  "ext/json/ext/generator/extconf.rb",
@@ -8,16 +8,30 @@ rescue LoadError
8
8
  end
9
9
 
10
10
  class BigDecimal
11
- # Import a JSON Marshalled object.
12
- #
13
- # method used for JSON marshalling support.
11
+
12
+ # See #as_json.
14
13
  def self.json_create(object)
15
14
  BigDecimal._load object['b']
16
15
  end
17
16
 
18
- # Marshal the object to JSON.
17
+ # Methods <tt>BigDecimal#as_json</tt> and +BigDecimal.json_create+ may be used
18
+ # to serialize and deserialize a \BigDecimal object;
19
+ # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
20
+ #
21
+ # \Method <tt>BigDecimal#as_json</tt> serializes +self+,
22
+ # returning a 2-element hash representing +self+:
23
+ #
24
+ # require 'json/add/bigdecimal'
25
+ # x = BigDecimal(2).as_json # => {"json_class"=>"BigDecimal", "b"=>"27:0.2e1"}
26
+ # y = BigDecimal(2.0, 4).as_json # => {"json_class"=>"BigDecimal", "b"=>"36:0.2e1"}
27
+ # z = BigDecimal(Complex(2, 0)).as_json # => {"json_class"=>"BigDecimal", "b"=>"27:0.2e1"}
28
+ #
29
+ # \Method +JSON.create+ deserializes such a hash, returning a \BigDecimal object:
30
+ #
31
+ # BigDecimal.json_create(x) # => 0.2e1
32
+ # BigDecimal.json_create(y) # => 0.2e1
33
+ # BigDecimal.json_create(z) # => 0.2e1
19
34
  #
20
- # method used for JSON marshalling support.
21
35
  def as_json(*)
22
36
  {
23
37
  JSON.create_id => self.class.name,
@@ -25,7 +39,19 @@ class BigDecimal
25
39
  }
26
40
  end
27
41
 
28
- # return the JSON value
42
+ # Returns a JSON string representing +self+:
43
+ #
44
+ # require 'json/add/bigdecimal'
45
+ # puts BigDecimal(2).to_json
46
+ # puts BigDecimal(2.0, 4).to_json
47
+ # puts BigDecimal(Complex(2, 0)).to_json
48
+ #
49
+ # Output:
50
+ #
51
+ # {"json_class":"BigDecimal","b":"27:0.2e1"}
52
+ # {"json_class":"BigDecimal","b":"36:0.2e1"}
53
+ # {"json_class":"BigDecimal","b":"27:0.2e1"}
54
+ #
29
55
  def to_json(*args)
30
56
  as_json.to_json(*args)
31
57
  end
@@ -5,14 +5,27 @@ end
5
5
 
6
6
  class Complex
7
7
 
8
- # Deserializes JSON string by converting Real value <tt>r</tt>, imaginary
9
- # value <tt>i</tt>, to a Complex object.
8
+ # See #as_json.
10
9
  def self.json_create(object)
11
10
  Complex(object['r'], object['i'])
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>Complex#as_json</tt> and +Complex.json_create+ may be used
14
+ # to serialize and deserialize a \Complex object;
15
+ # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
16
+ #
17
+ # \Method <tt>Complex#as_json</tt> serializes +self+,
18
+ # returning a 2-element hash representing +self+:
19
+ #
20
+ # require 'json/add/complex'
21
+ # x = Complex(2).as_json # => {"json_class"=>"Complex", "r"=>2, "i"=>0}
22
+ # y = Complex(2.0, 4).as_json # => {"json_class"=>"Complex", "r"=>2.0, "i"=>4}
23
+ #
24
+ # \Method +JSON.create+ deserializes such a hash, returning a \Complex object:
25
+ #
26
+ # Complex.json_create(x) # => (2+0i)
27
+ # Complex.json_create(y) # => (2.0+4i)
28
+ #
16
29
  def as_json(*)
17
30
  {
18
31
  JSON.create_id => self.class.name,
@@ -21,7 +34,17 @@ class Complex
21
34
  }
22
35
  end
23
36
 
24
- # Stores class name (Complex) along with real value <tt>r</tt> and imaginary value <tt>i</tt> as JSON string
37
+ # Returns a JSON string representing +self+:
38
+ #
39
+ # require 'json/add/complex'
40
+ # puts Complex(2).to_json
41
+ # puts Complex(2.0, 4).to_json
42
+ #
43
+ # Output:
44
+ #
45
+ # {"json_class":"Complex","r":2,"i":0}
46
+ # {"json_class":"Complex","r":2.0,"i":4}
47
+ #
25
48
  def to_json(*args)
26
49
  as_json.to_json(*args)
27
50
  end
data/lib/json/add/date.rb CHANGED
@@ -6,16 +6,29 @@ require 'date'
6
6
 
7
7
  class Date
8
8
 
9
- # Deserializes JSON string by converting Julian year <tt>y</tt>, month
10
- # <tt>m</tt>, day <tt>d</tt> and Day of Calendar Reform <tt>sg</tt> to Date.
9
+ # See #as_json.
11
10
  def self.json_create(object)
12
11
  civil(*object.values_at('y', 'm', 'd', 'sg'))
13
12
  end
14
13
 
15
14
  alias start sg unless method_defined?(:start)
16
15
 
17
- # Returns a hash, that will be turned into a JSON object and represent this
18
- # object.
16
+ # Methods <tt>Date#as_json</tt> and +Date.json_create+ may be used
17
+ # to serialize and deserialize a \Date object;
18
+ # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
19
+ #
20
+ # \Method <tt>Date#as_json</tt> serializes +self+,
21
+ # returning a 2-element hash representing +self+:
22
+ #
23
+ # require 'json/add/date'
24
+ # x = Date.today.as_json
25
+ # # => {"json_class"=>"Date", "y"=>2023, "m"=>11, "d"=>21, "sg"=>2299161.0}
26
+ #
27
+ # \Method +JSON.create+ deserializes such a hash, returning a \Date object:
28
+ #
29
+ # Date.json_create(x)
30
+ # # => #<Date: 2023-11-21 ((2460270j,0s,0n),+0s,2299161j)>
31
+ #
19
32
  def as_json(*)
20
33
  {
21
34
  JSON.create_id => self.class.name,
@@ -26,8 +39,15 @@ class Date
26
39
  }
27
40
  end
28
41
 
29
- # Stores class name (Date) with Julian year <tt>y</tt>, month <tt>m</tt>, day
30
- # <tt>d</tt> and Day of Calendar Reform <tt>sg</tt> as JSON string
42
+ # Returns a JSON string representing +self+:
43
+ #
44
+ # require 'json/add/date'
45
+ # puts Date.today.to_json
46
+ #
47
+ # Output:
48
+ #
49
+ # {"json_class":"Date","y":2023,"m":11,"d":21,"sg":2299161.0}
50
+ #
31
51
  def to_json(*args)
32
52
  as_json.to_json(*args)
33
53
  end
@@ -6,9 +6,7 @@ require 'date'
6
6
 
7
7
  class DateTime
8
8
 
9
- # Deserializes JSON string by converting year <tt>y</tt>, month <tt>m</tt>,
10
- # day <tt>d</tt>, hour <tt>H</tt>, minute <tt>M</tt>, second <tt>S</tt>,
11
- # offset <tt>of</tt> and Day of Calendar Reform <tt>sg</tt> to DateTime.
9
+ # See #as_json.
12
10
  def self.json_create(object)
13
11
  args = object.values_at('y', 'm', 'd', 'H', 'M', 'S')
14
12
  of_a, of_b = object['of'].split('/')
@@ -23,8 +21,21 @@ class DateTime
23
21
 
24
22
  alias start sg unless method_defined?(:start)
25
23
 
26
- # Returns a hash, that will be turned into a JSON object and represent this
27
- # object.
24
+ # Methods <tt>DateTime#as_json</tt> and +DateTime.json_create+ may be used
25
+ # to serialize and deserialize a \DateTime object;
26
+ # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
27
+ #
28
+ # \Method <tt>DateTime#as_json</tt> serializes +self+,
29
+ # returning a 2-element hash representing +self+:
30
+ #
31
+ # require 'json/add/datetime'
32
+ # x = DateTime.now.as_json
33
+ # # => {"json_class"=>"DateTime", "y"=>2023, "m"=>11, "d"=>21, "sg"=>2299161.0}
34
+ #
35
+ # \Method +JSON.create+ deserializes such a hash, returning a \DateTime object:
36
+ #
37
+ # DateTime.json_create(x) # BUG? Raises Date::Error "invalid date"
38
+ #
28
39
  def as_json(*)
29
40
  {
30
41
  JSON.create_id => self.class.name,
@@ -39,9 +50,15 @@ class DateTime
39
50
  }
40
51
  end
41
52
 
42
- # Stores class name (DateTime) with Julian year <tt>y</tt>, month <tt>m</tt>,
43
- # day <tt>d</tt>, hour <tt>H</tt>, minute <tt>M</tt>, second <tt>S</tt>,
44
- # offset <tt>of</tt> and Day of Calendar Reform <tt>sg</tt> as JSON string
53
+ # Returns a JSON string representing +self+:
54
+ #
55
+ # require 'json/add/datetime'
56
+ # puts DateTime.now.to_json
57
+ #
58
+ # Output:
59
+ #
60
+ # {"json_class":"DateTime","y":2023,"m":11,"d":21,"sg":2299161.0}
61
+ #
45
62
  def to_json(*args)
46
63
  as_json.to_json(*args)
47
64
  end
@@ -5,16 +5,27 @@ end
5
5
 
6
6
  class Exception
7
7
 
8
- # Deserializes JSON string by constructing new Exception object with message
9
- # <tt>m</tt> and backtrace <tt>b</tt> serialized with <tt>to_json</tt>
8
+ # See #as_json.
10
9
  def self.json_create(object)
11
10
  result = new(object['m'])
12
11
  result.set_backtrace object['b']
13
12
  result
14
13
  end
15
14
 
16
- # Returns a hash, that will be turned into a JSON object and represent this
17
- # object.
15
+ # Methods <tt>Exception#as_json</tt> and +Exception.json_create+ may be used
16
+ # to serialize and deserialize a \Exception object;
17
+ # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
18
+ #
19
+ # \Method <tt>Exception#as_json</tt> serializes +self+,
20
+ # returning a 2-element hash representing +self+:
21
+ #
22
+ # require 'json/add/exception'
23
+ # x = Exception.new('Foo').as_json # => {"json_class"=>"Exception", "m"=>"Foo", "b"=>nil}
24
+ #
25
+ # \Method +JSON.create+ deserializes such a hash, returning a \Exception object:
26
+ #
27
+ # Exception.json_create(x) # => #<Exception: Foo>
28
+ #
18
29
  def as_json(*)
19
30
  {
20
31
  JSON.create_id => self.class.name,
@@ -23,8 +34,15 @@ class Exception
23
34
  }
24
35
  end
25
36
 
26
- # Stores class name (Exception) with message <tt>m</tt> and backtrace array
27
- # <tt>b</tt> as JSON string
37
+ # Returns a JSON string representing +self+:
38
+ #
39
+ # require 'json/add/exception'
40
+ # puts Exception.new('Foo').to_json
41
+ #
42
+ # Output:
43
+ #
44
+ # {"json_class":"Exception","m":"Foo","b":null}
45
+ #
28
46
  def to_json(*args)
29
47
  as_json.to_json(*args)
30
48
  end
@@ -2,18 +2,34 @@
2
2
  unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
3
3
  require 'json'
4
4
  end
5
- require 'ostruct'
5
+ begin
6
+ require 'ostruct'
7
+ rescue LoadError
8
+ end
6
9
 
7
10
  class OpenStruct
8
11
 
9
- # Deserializes JSON string by constructing new Struct object with values
10
- # <tt>t</tt> serialized by <tt>to_json</tt>.
12
+ # See #as_json.
11
13
  def self.json_create(object)
12
14
  new(object['t'] || object[:t])
13
15
  end
14
16
 
15
- # Returns a hash, that will be turned into a JSON object and represent this
16
- # object.
17
+ # Methods <tt>OpenStruct#as_json</tt> and +OpenStruct.json_create+ may be used
18
+ # to serialize and deserialize a \OpenStruct object;
19
+ # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
20
+ #
21
+ # \Method <tt>OpenStruct#as_json</tt> serializes +self+,
22
+ # returning a 2-element hash representing +self+:
23
+ #
24
+ # require 'json/add/ostruct'
25
+ # x = OpenStruct.new('name' => 'Rowdy', :age => nil).as_json
26
+ # # => {"json_class"=>"OpenStruct", "t"=>{:name=>'Rowdy', :age=>nil}}
27
+ #
28
+ # \Method +JSON.create+ deserializes such a hash, returning a \OpenStruct object:
29
+ #
30
+ # OpenStruct.json_create(x)
31
+ # # => #<OpenStruct name='Rowdy', age=nil>
32
+ #
17
33
  def as_json(*)
18
34
  klass = self.class.name
19
35
  klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!"
@@ -23,9 +39,16 @@ class OpenStruct
23
39
  }
24
40
  end
25
41
 
26
- # Stores class name (OpenStruct) with this struct's values <tt>t</tt> as a
27
- # JSON string.
42
+ # Returns a JSON string representing +self+:
43
+ #
44
+ # require 'json/add/ostruct'
45
+ # puts OpenStruct.new('name' => 'Rowdy', :age => nil).to_json
46
+ #
47
+ # Output:
48
+ #
49
+ # {"json_class":"OpenStruct","t":{'name':'Rowdy',"age":null}}
50
+ #
28
51
  def to_json(*args)
29
52
  as_json.to_json(*args)
30
53
  end
31
- end
54
+ end if defined?(::OpenStruct)
@@ -5,24 +5,28 @@ end
5
5
 
6
6
  class Range
7
7
 
8
- # Returns a new \Range object constructed from <tt>object['a']</tt>,
9
- # which must be an array of values suitable for a call to Range.new:
10
- #
11
- # require 'json/add/range'
12
- # Range.json_create({"a"=>[1, 4]}) # => 1..4
13
- # Range.json_create({"a"=>[1, 4, true]}) # => 1...4
14
- # Range.json_create({"a" => ['a', 'd']}) # => "a".."d"
15
- #
8
+ # See #as_json.
16
9
  def self.json_create(object)
17
10
  new(*object['a'])
18
11
  end
19
12
 
20
- # Returns a 2-element hash representing +self+:
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+:
21
19
  #
22
20
  # require 'json/add/range'
23
- # (1..4).as_json # => {"json_class"=>"Range", "a"=>[1, 4, false]}
24
- # (1...4).as_json # => {"json_class"=>"Range", "a"=>[1, 4, true]}
25
- # ('a'..'d').as_json # => {"json_class"=>"Range", "a"=>["a", "d", false]}
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"
26
30
  #
27
31
  def as_json(*)
28
32
  {
@@ -34,9 +38,15 @@ class Range
34
38
  # Returns a JSON string representing +self+:
35
39
  #
36
40
  # require 'json/add/range'
37
- # (1..4).to_json # => "{\"json_class\":\"Range\",\"a\":[1,4,false]}"
38
- # (1...4).to_json # => "{\"json_class\":\"Range\",\"a\":[1,4,true]}"
39
- # ('a'..'d').to_json # => "{\"json_class\":\"Range\",\"a\":[\"a\",\"d\",false]}"
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]}
40
50
  #
41
51
  def to_json(*args)
42
52
  as_json.to_json(*args)
@@ -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,9 @@
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
+
6
7
  NOT_SET = Object.new.freeze
7
8
  private_constant :NOT_SET
8
9
 
@@ -611,17 +612,18 @@ module JSON
611
612
  # puts File.read(path)
612
613
  # Output:
613
614
  # {"foo":[0,1],"bar":{"baz":2,"bat":3},"bam":"bad"}
614
- def dump(obj, anIO = nil, limit = nil, strict: NOT_SET)
615
- if anIO and limit.nil?
616
- anIO = anIO.to_io if anIO.respond_to?(:to_io)
617
- unless anIO.respond_to?(:write)
618
- limit = anIO
619
- anIO = nil
620
- 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
621
623
  end
622
624
  opts = JSON.dump_default_options
623
625
  opts = opts.merge(:max_nesting => limit) if limit
624
- opts[:strict] = strict if NOT_SET != strict
626
+ opts = merge_dump_options(opts, **kwargs) if kwargs
625
627
  result = generate(obj, opts)
626
628
  if anIO
627
629
  anIO.write result
@@ -637,6 +639,15 @@ module JSON
637
639
  def self.iconv(to, from, string)
638
640
  string.encode(to, from)
639
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
640
651
  end
641
652
 
642
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
data/lib/json/version.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: false
2
2
  module JSON
3
3
  # JSON version
4
- VERSION = '2.7.0'
4
+ VERSION = '2.7.2'
5
5
  VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc:
6
6
  VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
7
7
  VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.7.0
4
+ version: 2.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Frank
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2023-12-01 00:00:00.000000000 Z
10
+ date: 2024-04-04 00:00:00.000000000 Z
12
11
  dependencies: []
13
12
  description: This is a JSON implementation as a Ruby extension in C.
14
13
  email: flori@ping.de
@@ -23,7 +22,6 @@ files:
23
22
  - CHANGES.md
24
23
  - LICENSE
25
24
  - README.md
26
- - VERSION
27
25
  - ext/json/ext/fbuffer/fbuffer.h
28
26
  - ext/json/ext/generator/depend
29
27
  - ext/json/ext/generator/extconf.rb
@@ -68,7 +66,6 @@ metadata:
68
66
  homepage_uri: https://flori.github.io/json
69
67
  source_code_uri: https://github.com/flori/json
70
68
  wiki_uri: https://github.com/flori/json/wiki
71
- post_install_message:
72
69
  rdoc_options:
73
70
  - "--title"
74
71
  - JSON implementation for Ruby
@@ -87,8 +84,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
87
84
  - !ruby/object:Gem::Version
88
85
  version: '0'
89
86
  requirements: []
90
- rubygems_version: 3.5.0.dev
91
- signing_key:
87
+ rubygems_version: 3.6.0.dev
92
88
  specification_version: 4
93
89
  summary: JSON Implementation for Ruby
94
90
  test_files: []
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 2.7.0