json 1.1.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of json might be problematic. Click here for more details.

@@ -8,8 +8,12 @@
8
8
  #define EVIL 0x666
9
9
 
10
10
  static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
11
+ static VALUE CNaN, CInfinity, CMinusInfinity;
11
12
 
12
- static ID i_json_creatable_p, i_json_create, i_create_id, i_chr, i_max_nesting;
13
+ static ID i_json_creatable_p, i_json_create, i_create_id, i_chr, i_max_nesting,
14
+ i_allow_nan;
15
+
16
+ #define MinusInfinity "-Infinity"
13
17
 
14
18
  typedef struct JSON_ParserStruct {
15
19
  VALUE Vsource;
@@ -19,6 +23,7 @@ typedef struct JSON_ParserStruct {
19
23
  VALUE create_id;
20
24
  int max_nesting;
21
25
  int current_nesting;
26
+ int allow_nan;
22
27
  } JSON_Parser;
23
28
 
24
29
  static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result);
@@ -47,7 +52,10 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
47
52
  Vnull = 'null';
48
53
  Vfalse = 'false';
49
54
  Vtrue = 'true';
50
- begin_value = [nft"\-[{] | digit;
55
+ VNaN = 'NaN';
56
+ VInfinity = 'Infinity';
57
+ VMinusInfinity = '-Infinity';
58
+ begin_value = [nft"\-[{NI] | digit;
51
59
  begin_object = '{';
52
60
  end_object = '}';
53
61
  begin_array = '[';
@@ -133,6 +141,20 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
133
141
  action parse_true {
134
142
  *result = Qtrue;
135
143
  }
144
+ action parse_nan {
145
+ if (json->allow_nan) {
146
+ *result = CNaN;
147
+ } else {
148
+ rb_raise(eParserError, "unexpected token at '%s'", p - 2);
149
+ }
150
+ }
151
+ action parse_infinity {
152
+ if (json->allow_nan) {
153
+ *result = CInfinity;
154
+ } else {
155
+ rb_raise(eParserError, "unexpected token at '%s'", p - 8);
156
+ }
157
+ }
136
158
  action parse_string {
137
159
  char *np = JSON_parse_string(json, fpc, pe, result);
138
160
  if (np == NULL) fbreak; else fexec np;
@@ -140,6 +162,15 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
140
162
 
141
163
  action parse_number {
142
164
  char *np;
165
+ if(pe > fpc + 9 && !strncmp(MinusInfinity, fpc, 9)) {
166
+ if (json->allow_nan) {
167
+ *result = CMinusInfinity;
168
+ fexec p + 10;
169
+ fbreak;
170
+ } else {
171
+ rb_raise(eParserError, "unexpected token at '%s'", p);
172
+ }
173
+ }
143
174
  np = JSON_parse_float(json, fpc, pe, result);
144
175
  if (np != NULL) fexec np;
145
176
  np = JSON_parse_integer(json, fpc, pe, result);
@@ -169,6 +200,8 @@ main := (
169
200
  Vnull @parse_null |
170
201
  Vfalse @parse_false |
171
202
  Vtrue @parse_true |
203
+ VNaN @parse_nan |
204
+ VInfinity @parse_infinity |
172
205
  begin_number >parse_number |
173
206
  begin_string >parse_string |
174
207
  begin_array >parse_array |
@@ -435,7 +468,11 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
435
468
  *
436
469
  * _opts_ can have the following keys:
437
470
  * * *max_nesting*: The maximum depth of nesting allowed in the parsed data
438
- * structures. Disable depth checking with :max_nesting => false.
471
+ * structures. Disable depth checking with :max_nesting => false|nil|0, it
472
+ * defaults to 19.
473
+ * * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
474
+ * defiance of RFC 4627 to be parsed by the Parser. This option defaults to
475
+ * false.
439
476
  */
440
477
  static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
441
478
  {
@@ -451,14 +488,15 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
451
488
  rb_raise(eParserError, "A JSON text must at least contain two octets!");
452
489
  }
453
490
  json->max_nesting = 19;
491
+ json->allow_nan = 0;
454
492
  if (!NIL_P(opts)) {
455
493
  opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
456
494
  if (NIL_P(opts)) {
457
495
  rb_raise(rb_eArgError, "opts needs to be like a hash");
458
496
  } else {
459
- VALUE s_max_nesting = ID2SYM(i_max_nesting);
460
- if (st_lookup(RHASH(opts)->tbl, s_max_nesting, 0)) {
461
- VALUE max_nesting = rb_hash_aref(opts, s_max_nesting);
497
+ VALUE tmp = ID2SYM(i_max_nesting);
498
+ if (st_lookup(RHASH(opts)->tbl, tmp, 0)) {
499
+ VALUE max_nesting = rb_hash_aref(opts, tmp);
462
500
  if (RTEST(max_nesting)) {
463
501
  Check_Type(max_nesting, T_FIXNUM);
464
502
  json->max_nesting = FIX2INT(max_nesting);
@@ -466,6 +504,11 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
466
504
  json->max_nesting = 0;
467
505
  }
468
506
  }
507
+ tmp = ID2SYM(i_allow_nan);
508
+ if (st_lookup(RHASH(opts)->tbl, tmp, 0)) {
509
+ VALUE allow_nan = rb_hash_aref(opts, tmp);
510
+ if (RTEST(allow_nan)) json->allow_nan = 1;
511
+ }
469
512
  }
470
513
  }
471
514
  json->current_nesting = 0;
@@ -561,9 +604,14 @@ void Init_parser()
561
604
  rb_define_method(cParser, "parse", cParser_parse, 0);
562
605
  rb_define_method(cParser, "source", cParser_source, 0);
563
606
 
607
+ CNaN = rb_const_get(mJSON, rb_intern("NaN"));
608
+ CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
609
+ CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
610
+
564
611
  i_json_creatable_p = rb_intern("json_creatable?");
565
612
  i_json_create = rb_intern("json_create");
566
613
  i_create_id = rb_intern("create_id");
567
614
  i_chr = rb_intern("chr");
568
615
  i_max_nesting = rb_intern("max_nesting");
616
+ i_allow_nan = rb_intern("allow_nan");
569
617
  }
@@ -47,6 +47,27 @@ require 'json/common'
47
47
  #
48
48
  # * http://json.rubyforge.org
49
49
  #
50
+ # == Usage
51
+ #
52
+ # To use JSON you can
53
+ # require 'json'
54
+ # to load the installed variant (either the extension 'json' or the pure
55
+ # variant 'json_pure'). If you have installed the extension variant, you can
56
+ # pick either the extension variant or the pure variant by typing
57
+ # require 'json/ext'
58
+ # or
59
+ # require 'json/pure'
60
+ #
61
+ # You can choose to load a set of common additions to ruby core's objects if
62
+ # you
63
+ # require 'json/add/core'
64
+ #
65
+ # To get the best compatibility to rails' JSON implementation, you can
66
+ # require 'json/add/rails'
67
+ #
68
+ # Both of the additions attempt to require 'json' (like above) first, if it has
69
+ # not been required yet.
70
+ #
50
71
  # == Speed Comparisons
51
72
  #
52
73
  # I have created some benchmark results (see the benchmarks subdir of the
@@ -207,4 +228,6 @@ module JSON
207
228
  require 'json/pure'
208
229
  end
209
230
  end
231
+
232
+ JSON_LOADED = true
210
233
  end
@@ -0,0 +1,119 @@
1
+ # This file contains implementations of ruby core's custom objects for
2
+ # serialisation/deserialisation.
3
+
4
+ unless Object.const_defined?(:JSON) and ::JSON.const_defined?(:JSON_LOADED) and
5
+ ::JSON::JSON_LOADED
6
+ require 'json'
7
+ end
8
+
9
+ class Time
10
+ def self.json_create(object)
11
+ at(*object.values_at('s', 'u'))
12
+ end
13
+
14
+ def to_json(*args)
15
+ {
16
+ 'json_class' => self.class.name,
17
+ 's' => tv_sec,
18
+ 'u' => tv_usec,
19
+ }.to_json(*args)
20
+ end
21
+ end
22
+
23
+ class Date
24
+ def self.json_create(object)
25
+ civil(*object.values_at('y', 'm', 'd', 'sg'))
26
+ end
27
+
28
+ def to_json(*args)
29
+ {
30
+ 'json_class' => self.class.name,
31
+ 'y' => year,
32
+ 'm' => month,
33
+ 'd' => day,
34
+ 'sg' => sg,
35
+ }.to_json(*args)
36
+ end
37
+ end
38
+
39
+ class DateTime
40
+ def self.json_create(object)
41
+ args = object.values_at('y', 'm', 'd', 'H', 'M', 'S')
42
+ of_a, of_b = object['of'].split('/')
43
+ args << Rational(of_a.to_i, of_b.to_i)
44
+ args << object['sg']
45
+ civil(*args)
46
+ end
47
+
48
+ def to_json(*args)
49
+ {
50
+ 'json_class' => self.class.name,
51
+ 'y' => year,
52
+ 'm' => month,
53
+ 'd' => day,
54
+ 'H' => hour,
55
+ 'M' => min,
56
+ 'S' => sec,
57
+ 'of' => offset,
58
+ 'sg' => sg,
59
+ }.to_json(*args)
60
+ end
61
+ end
62
+
63
+ class Range
64
+ def self.json_create(object)
65
+ new(*object['a'])
66
+ end
67
+
68
+ def to_json(*args)
69
+ {
70
+ 'json_class' => self.class.name,
71
+ 'a' => [ first, last, exclude_end? ]
72
+ }.to_json(*args)
73
+ end
74
+ end
75
+
76
+ class Struct
77
+ def self.json_create(object)
78
+ new(*object['v'])
79
+ end
80
+
81
+ def to_json(*args)
82
+ klass = self.class.name
83
+ klass.empty? and raise JSON::JSONError, "Only named structs are supported!"
84
+ {
85
+ 'json_class' => klass,
86
+ 'v' => values,
87
+ }.to_json(*args)
88
+ end
89
+ end
90
+
91
+ class Exception
92
+ def self.json_create(object)
93
+ result = new(object['m'])
94
+ result.set_backtrace object['b']
95
+ result
96
+ end
97
+
98
+ def to_json(*args)
99
+ {
100
+ 'json_class' => self.class.name,
101
+ 'm' => message,
102
+ 'b' => backtrace,
103
+ }.to_json(*args)
104
+ end
105
+ end
106
+
107
+ class Regexp
108
+ def self.json_create(object)
109
+ new(object['s'], object['o'])
110
+ end
111
+
112
+ def to_json(*)
113
+ {
114
+ 'json_class' => self.class.name,
115
+ 'o' => options,
116
+ 's' => source,
117
+ }.to_json
118
+ end
119
+ end
@@ -0,0 +1,52 @@
1
+ # This file contains implementations of rails custom objects for
2
+ # serialisation/deserialisation.
3
+
4
+ unless Object.const_defined?(:JSON) and ::JSON.const_defined?(:JSON_LOADED) and
5
+ ::JSON::JSON_LOADED
6
+ require 'json'
7
+ end
8
+
9
+ class Object
10
+ def self.json_create(object)
11
+ obj = new
12
+ for key, value in object
13
+ next if key == 'json_class'
14
+ instance_variable_set "@#{key}", value
15
+ end
16
+ obj
17
+ end
18
+
19
+ def to_json(*a)
20
+ result = {
21
+ 'json_class' => self.class.name
22
+ }
23
+ instance_variables.inject(result) do |r, name|
24
+ r[name[1..-1]] = instance_variable_get name
25
+ r
26
+ end
27
+ result.to_json(*a)
28
+ end
29
+ end
30
+
31
+ module Enumerable
32
+ def to_json(*a)
33
+ to_a.to_json(*a)
34
+ end
35
+ end
36
+
37
+ # class Regexp
38
+ # def to_json(*)
39
+ # inspect
40
+ # end
41
+ # end
42
+ #
43
+ # The above rails definition has some problems:
44
+ #
45
+ # 1. { 'foo' => /bar/ }.to_json # => "{foo: /bar/}"
46
+ # This isn't valid JSON, because the regular expression syntax is not
47
+ # defined in RFC 4627. (And unquoted strings are disallowed there, too.)
48
+ # Though it is valid Javascript.
49
+ #
50
+ # 2. { 'foo' => /bar/mix }.to_json # => "{foo: /bar/mix}"
51
+ # This isn't even valid Javascript.
52
+
@@ -2,14 +2,17 @@ require 'json/version'
2
2
 
3
3
  module JSON
4
4
  class << self
5
- # If object is string like parse the string and return the parsed result as a
6
- # Ruby data structure. Otherwise generate a JSON text from the Ruby data
7
- # structure object and return it.
8
- def [](object)
5
+ # If _object_ is string like parse the string and return the parsed result
6
+ # as a Ruby data structure. Otherwise generate a JSON text from the Ruby
7
+ # data structure object and return it.
8
+ #
9
+ # The _opts_ argument is passed through to generate/parse respectively, see
10
+ # generate and parse for their documentation.
11
+ def [](object, opts = {})
9
12
  if object.respond_to? :to_str
10
- JSON.parse(object.to_str)
13
+ JSON.parse(object.to_str, opts => {})
11
14
  else
12
- JSON.generate(object)
15
+ JSON.generate(object, opts => {})
13
16
  end
14
17
  end
15
18
 
@@ -71,6 +74,12 @@ module JSON
71
74
  end
72
75
  self.create_id = 'json_class'
73
76
 
77
+ NaN = (-1.0) ** 0.5
78
+
79
+ Infinity = 1.0/0
80
+
81
+ MinusInfinity = -Infinity
82
+
74
83
  # The base exception for JSON errors.
75
84
  class JSONError < StandardError; end
76
85
 
@@ -101,29 +110,79 @@ module JSON
101
110
  # _opts_ can have the following
102
111
  # keys:
103
112
  # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
104
- # structures. Disable depth checking with :max_nesting => false.
113
+ # structures. Disable depth checking with :max_nesting => false, it defaults
114
+ # to 19.
115
+ # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
116
+ # defiance of RFC 4627 to be parsed by the Parser. This option defaults
117
+ # to false.
105
118
  def parse(source, opts = {})
106
119
  JSON.parser.new(source, opts).parse
107
120
  end
108
121
 
122
+ # Parse the JSON string _source_ into a Ruby data structure and return it.
123
+ # The bang version of the parse method, defaults to the more dangerous values
124
+ # for the _opts_ hash, so be sure only to parse trusted _source_ strings.
125
+ #
126
+ # _opts_ can have the following keys:
127
+ # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
128
+ # structures. Enable depth checking with :max_nesting => anInteger. The parse!
129
+ # methods defaults to not doing max depth checking: This can be dangerous,
130
+ # if someone wants to fill up your stack.
131
+ # * *allow_nan*: If set to true, allow NaN, Infinity, and -Infinity in
132
+ # defiance of RFC 4627 to be parsed by the Parser. This option defaults
133
+ # to true.
134
+ def parse!(source, opts = {})
135
+ opts = {
136
+ :max_nesting => false,
137
+ :allow_nan => true
138
+ }.update(opts)
139
+ JSON.parser.new(source, opts).parse
140
+ end
141
+
109
142
  # Unparse the Ruby data structure _obj_ into a single line JSON string and
110
- # return it. _state_ is a JSON::State object, that can be used to configure
111
- # the output further.
143
+ # return it. _state_ is
144
+ # * a JSON::State object,
145
+ # * or a Hash like object (responding to to_hash),
146
+ # * an object convertible into a hash by a to_h method,
147
+ # that is used as or to configure a State object.
112
148
  #
113
149
  # It defaults to a state object, that creates the shortest possible JSON text
114
- # in one line and only checks for circular data structures. If you are sure,
115
- # that the objects don't contain any circles, you can set _state_ to nil, to
116
- # disable these checks in order to create the JSON text faster. See also
117
- # fast_generate.
118
- def generate(obj, state = JSON.state.new)
150
+ # in one line, checks for circular data structures and doesn't allow NaN,
151
+ # Infinity, and -Infinity.
152
+ #
153
+ # A _state_ hash can have the following keys:
154
+ # * *indent*: a string used to indent levels (default: ''),
155
+ # * *space*: a string that is put after, a : or , delimiter (default: ''),
156
+ # * *space_before*: a string that is put before a : pair delimiter (default: ''),
157
+ # * *object_nl*: a string that is put at the end of a JSON object (default: ''),
158
+ # * *array_nl*: a string that is put at the end of a JSON array (default: ''),
159
+ # * *check_circular*: true if checking for circular data structures
160
+ # should be done (the default), false otherwise.
161
+ # * *allow_nan*: true if NaN, Infinity, and -Infinity should be
162
+ # generated, otherwise an exception is thrown, if these values are
163
+ # encountered. This options defaults to false.
164
+ #
165
+ # See also the fast_generate for the fastest creation method with the least
166
+ # amount of sanity checks, and the pretty_generate method for some
167
+ # defaults for a pretty output.
168
+ def generate(obj, state = nil)
169
+ if state
170
+ state = State.from_state(state)
171
+ else
172
+ state = State.new
173
+ end
119
174
  obj.to_json(state)
120
175
  end
121
176
 
177
+ # :stopdoc:
178
+ # I want to deprecate these later, so I'll first be silent about them, and later delete them.
122
179
  alias unparse generate
123
180
  module_function :unparse
181
+ # :startdoc:
124
182
 
125
183
  # Unparse the Ruby data structure _obj_ into a single line JSON string and
126
- # return it. This method disables the checks for circles in Ruby objects.
184
+ # return it. This method disables the checks for circles in Ruby objects, and
185
+ # also generates NaN, Infinity, and, -Infinity float values.
127
186
  #
128
187
  # *WARNING*: Be careful not to pass any Ruby data structures with circles as
129
188
  # _obj_ argument, because this will cause JSON to go into an infinite loop.
@@ -131,12 +190,18 @@ module JSON
131
190
  obj.to_json(nil)
132
191
  end
133
192
 
193
+ # :stopdoc:
194
+ # I want to deprecate these later, so I'll first be silent about them, and later delete them.
134
195
  alias fast_unparse fast_generate
135
196
  module_function :fast_unparse
197
+ # :startdoc:
136
198
 
137
199
  # Unparse the Ruby data structure _obj_ into a JSON string and return it. The
138
200
  # returned string is a prettier form of the string returned by #unparse.
139
- def pretty_generate(obj)
201
+ #
202
+ # The _opts_ argument can be used to configure the generator, see the
203
+ # generate method for a more detailed explanation.
204
+ def pretty_generate(obj, opts = nil)
140
205
  state = JSON.state.new(
141
206
  :indent => ' ',
142
207
  :space => ' ',
@@ -144,11 +209,94 @@ module JSON
144
209
  :array_nl => "\n",
145
210
  :check_circular => true
146
211
  )
212
+ if opts
213
+ if opts.respond_to? :to_hash
214
+ opts = opts.to_hash
215
+ elsif opts.respond_to? :to_h
216
+ opts = opts.to_h
217
+ else
218
+ raise TypeError, "can't convert #{opts.class} into Hash"
219
+ end
220
+ state.configure(opts)
221
+ end
147
222
  obj.to_json(state)
148
223
  end
149
224
 
225
+ # :stopdoc:
226
+ # I want to deprecate these later, so I'll first be silent about them, and later delete them.
150
227
  alias pretty_unparse pretty_generate
151
228
  module_function :pretty_unparse
229
+ # :startdoc:
230
+
231
+ # Load a ruby data structure from a JSON _source_ and return it. A source can
232
+ # either be a string like object, an IO like object, or an object responding
233
+ # to the read method. If _proc_ was given, it will be called with any nested
234
+ # Ruby object as an argument recursively in depth first order.
235
+ #
236
+ # This method is part of the implementation of the load/dump interface of
237
+ # Marshal and YAML.
238
+ def load(source, proc = nil)
239
+ if source.respond_to? :to_str
240
+ source = source.to_str
241
+ elsif source.respond_to? :to_io
242
+ source = source.to_io.read
243
+ else
244
+ source = source.read
245
+ end
246
+ result = parse(source, :max_nesting => false, :allow_nan => true)
247
+ recurse_proc(result, &proc) if proc
248
+ result
249
+ end
250
+
251
+ def recurse_proc(result, &proc)
252
+ case result
253
+ when Array
254
+ result.each { |x| recurse_proc x, &proc }
255
+ proc.call result
256
+ when Hash
257
+ result.each { |x, y| recurse_proc x, &proc; recurse_proc y, &proc }
258
+ proc.call result
259
+ else
260
+ proc.call result
261
+ end
262
+ end
263
+ private :recurse_proc
264
+ module_function :recurse_proc
265
+
266
+ alias restore load
267
+ module_function :restore
268
+
269
+ # Dumps _obj_ as a JSON string, i.e. calls generate on the object and returns
270
+ # the result.
271
+ #
272
+ # If anIO (an IO like object or an object that responds to the write method)
273
+ # was given, the resulting JSON is written to it.
274
+ #
275
+ # If the number of nested arrays or objects exceeds _limit_ an ArgumentError
276
+ # exception is raised. This argument is similar (but not exactly the
277
+ # same!) to the _limit_ argument in Marshal.dump.
278
+ #
279
+ # This method is part of the implementation of the load/dump interface of
280
+ # Marshal and YAML.
281
+ def dump(obj, anIO = nil, limit = nil)
282
+ if anIO and limit.nil?
283
+ anIO = anIO.to_io if anIO.respond_to?(:to_io)
284
+ unless anIO.respond_to?(:write)
285
+ limit = anIO
286
+ anIO = nil
287
+ end
288
+ end
289
+ limit ||= 0
290
+ result = generate(obj, :allow_nan => true, :max_nesting => limit)
291
+ if anIO
292
+ anIO.write result
293
+ anIO
294
+ else
295
+ result
296
+ end
297
+ rescue JSON::NestingError
298
+ raise ArgumentError, "exceed depth limit"
299
+ end
152
300
  end
153
301
 
154
302
  module ::Kernel
@@ -156,7 +304,7 @@ module ::Kernel
156
304
  # one line.
157
305
  def j(*objs)
158
306
  objs.each do |obj|
159
- puts JSON::generate(obj)
307
+ puts JSON::generate(obj, :allow_nan => true, :max_nesting => false)
160
308
  end
161
309
  nil
162
310
  end
@@ -165,19 +313,22 @@ module ::Kernel
165
313
  # indentation and over many lines.
166
314
  def jj(*objs)
167
315
  objs.each do |obj|
168
- puts JSON::pretty_generate(obj)
316
+ puts JSON::pretty_generate(obj, :allow_nan => true, :max_nesting => false)
169
317
  end
170
318
  nil
171
319
  end
172
320
 
173
- # If object is string like parse the string and return the parsed result as a
174
- # Ruby data structure. Otherwise generate a JSON text from the Ruby data
321
+ # If _object_ is string like parse the string and return the parsed result as
322
+ # a Ruby data structure. Otherwise generate a JSON text from the Ruby data
175
323
  # structure object and return it.
176
- def JSON(object)
324
+ #
325
+ # The _opts_ argument is passed through to generate/parse respectively, see
326
+ # generate and parse for their documentation.
327
+ def JSON(object, opts = {})
177
328
  if object.respond_to? :to_str
178
- JSON.parse(object.to_str)
329
+ JSON.parse(object.to_str, opts)
179
330
  else
180
- JSON.generate(object)
331
+ JSON.generate(object, opts)
181
332
  end
182
333
  end
183
334
  end