json 1.1.9 → 1.2.0
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.
- data/CHANGES +7 -0
- data/README +316 -34
- data/Rakefile +48 -28
- data/VERSION +1 -1
- data/ext/json/ext/generator/generator.c +21 -5
- data/ext/json/ext/generator/unicode.c +3 -3
- data/ext/json/ext/parser/parser.c +142 -91
- data/ext/json/ext/parser/parser.rl +68 -17
- data/ext/json/ext/parser/unicode.c +2 -2
- data/lib/json/common.rb +32 -17
- data/lib/json/pure/generator.rb +24 -10
- data/lib/json/pure/parser.rb +35 -1
- data/lib/json/version.rb +1 -1
- data/tests/test_json.rb +25 -17
- data/tests/test_json_encoding.rb +67 -0
- data/tests/test_json_generate.rb +21 -7
- data/tests/test_json_rails.rb +1 -1
- metadata +7 -6
- data/doc-main.txt +0 -283
@@ -19,15 +19,19 @@
|
|
19
19
|
#ifdef HAVE_RUBY_ENCODING_H
|
20
20
|
#include "ruby/encoding.h"
|
21
21
|
#define FORCE_UTF8(obj) rb_enc_associate((obj), rb_utf8_encoding())
|
22
|
+
static VALUE mEncoding_ASCII_8BIT, mEncoding_UTF_8, mEncoding_UTF_16BE,
|
23
|
+
mEncoding_UTF_16LE, mEncoding_UTF_32BE, mEncoding_UTF_32LE;
|
24
|
+
static ID i_encoding, i_encode, i_encode_bang, i_force_encoding;
|
22
25
|
#else
|
23
26
|
#define FORCE_UTF8(obj)
|
27
|
+
static ID i_iconv;
|
24
28
|
#endif
|
25
29
|
|
26
30
|
static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
|
27
31
|
static VALUE CNaN, CInfinity, CMinusInfinity;
|
28
32
|
|
29
33
|
static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
30
|
-
i_chr, i_max_nesting, i_allow_nan, i_object_class, i_array_class;
|
34
|
+
i_chr, i_max_nesting, i_allow_nan, i_object_class, i_array_class;
|
31
35
|
|
32
36
|
#define MinusInfinity "-Infinity"
|
33
37
|
|
@@ -484,6 +488,54 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
484
488
|
*
|
485
489
|
*/
|
486
490
|
|
491
|
+
inline static VALUE convert_encoding(VALUE source)
|
492
|
+
{
|
493
|
+
char *ptr = RSTRING_PTR(source);
|
494
|
+
long len = RSTRING_LEN(source);
|
495
|
+
if (len < 2) {
|
496
|
+
rb_raise(eParserError, "A JSON text must at least contain two octets!");
|
497
|
+
}
|
498
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
499
|
+
{
|
500
|
+
VALUE encoding = rb_funcall(source, i_encoding, 0);
|
501
|
+
if (encoding == mEncoding_ASCII_8BIT) {
|
502
|
+
if (len >= 4 && ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0) {
|
503
|
+
source = rb_str_dup(source);
|
504
|
+
rb_funcall(source, i_force_encoding, 1, mEncoding_UTF_32BE);
|
505
|
+
source = rb_funcall(source, i_encode_bang, 1, mEncoding_UTF_8);
|
506
|
+
} else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
|
507
|
+
source = rb_str_dup(source);
|
508
|
+
rb_funcall(source, i_force_encoding, 1, mEncoding_UTF_16BE);
|
509
|
+
source = rb_funcall(source, i_encode_bang, 1, mEncoding_UTF_8);
|
510
|
+
} else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
|
511
|
+
source = rb_str_dup(source);
|
512
|
+
rb_funcall(source, i_force_encoding, 1, mEncoding_UTF_32LE);
|
513
|
+
source = rb_funcall(source, i_encode_bang, 1, mEncoding_UTF_8);
|
514
|
+
} else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
|
515
|
+
source = rb_str_dup(source);
|
516
|
+
rb_funcall(source, i_force_encoding, 1, mEncoding_UTF_16LE);
|
517
|
+
source = rb_funcall(source, i_encode_bang, 1, mEncoding_UTF_8);
|
518
|
+
} else {
|
519
|
+
source = rb_funcall(source, i_force_encoding, 1, mEncoding_UTF_8);
|
520
|
+
}
|
521
|
+
} else {
|
522
|
+
source = rb_funcall(source, i_encode, 1, mEncoding_UTF_8);
|
523
|
+
}
|
524
|
+
}
|
525
|
+
#else
|
526
|
+
if (len >= 4 && ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0) {
|
527
|
+
source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-32be"), source);
|
528
|
+
} else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
|
529
|
+
source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-16be"), source);
|
530
|
+
} else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
|
531
|
+
source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-32le"), source);
|
532
|
+
} else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
|
533
|
+
source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-16le"), source);
|
534
|
+
}
|
535
|
+
#endif
|
536
|
+
return source;
|
537
|
+
}
|
538
|
+
|
487
539
|
/*
|
488
540
|
* call-seq: new(source, opts => {})
|
489
541
|
*
|
@@ -514,12 +566,9 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
514
566
|
VALUE source, opts;
|
515
567
|
GET_STRUCT;
|
516
568
|
rb_scan_args(argc, argv, "11", &source, &opts);
|
517
|
-
source = StringValue(source);
|
569
|
+
source = convert_encoding(StringValue(source));
|
518
570
|
ptr = RSTRING_PTR(source);
|
519
571
|
len = RSTRING_LEN(source);
|
520
|
-
if (len < 2) {
|
521
|
-
rb_raise(eParserError, "A JSON text must at least contain two octets!");
|
522
|
-
}
|
523
572
|
if (!NIL_P(opts)) {
|
524
573
|
opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
|
525
574
|
if (NIL_P(opts)) {
|
@@ -576,18 +625,6 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
576
625
|
json->array_class = Qnil;
|
577
626
|
}
|
578
627
|
json->current_nesting = 0;
|
579
|
-
/*
|
580
|
-
Convert these?
|
581
|
-
if (len >= 4 && ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0) {
|
582
|
-
rb_raise(eParserError, "Only UTF8 octet streams are supported atm!");
|
583
|
-
} else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
|
584
|
-
rb_raise(eParserError, "Only UTF8 octet streams are supported atm!");
|
585
|
-
} else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
|
586
|
-
rb_raise(eParserError, "Only UTF8 octet streams are supported atm!");
|
587
|
-
} else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
|
588
|
-
rb_raise(eParserError, "Only UTF8 octet streams are supported atm!");
|
589
|
-
}
|
590
|
-
*/
|
591
628
|
json->len = len;
|
592
629
|
json->source = ptr;
|
593
630
|
json->Vsource = source;
|
@@ -683,4 +720,18 @@ void Init_parser()
|
|
683
720
|
i_allow_nan = rb_intern("allow_nan");
|
684
721
|
i_object_class = rb_intern("object_class");
|
685
722
|
i_array_class = rb_intern("array_class");
|
723
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
724
|
+
mEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8"));
|
725
|
+
mEncoding_UTF_16BE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-16be"));
|
726
|
+
mEncoding_UTF_16LE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-16le"));
|
727
|
+
mEncoding_UTF_32BE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-32be"));
|
728
|
+
mEncoding_UTF_32LE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-32le"));
|
729
|
+
mEncoding_ASCII_8BIT = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("ascii-8bit"));
|
730
|
+
i_encoding = rb_intern("encoding");
|
731
|
+
i_encode = rb_intern("encode");
|
732
|
+
i_encode_bang = rb_intern("encode!");
|
733
|
+
i_force_encoding = rb_intern("force_encoding");
|
734
|
+
#else
|
735
|
+
i_iconv = rb_intern("iconv");
|
736
|
+
#endif
|
686
737
|
}
|
@@ -105,7 +105,7 @@ char *JSON_convert_UTF16_to_UTF8 (
|
|
105
105
|
} else if (flags == strictConversion) { /* it's an unpaired high surrogate */
|
106
106
|
ruby_xfree(tmp);
|
107
107
|
rb_raise(rb_path2class("JSON::ParserError"),
|
108
|
-
"
|
108
|
+
"\\uXXXX is illegal/malformed utf-16 near %s", source);
|
109
109
|
}
|
110
110
|
} else { /* We don't have the 16 bits following the high surrogate. */
|
111
111
|
ruby_xfree(tmp);
|
@@ -118,7 +118,7 @@ char *JSON_convert_UTF16_to_UTF8 (
|
|
118
118
|
if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
|
119
119
|
ruby_xfree(tmp);
|
120
120
|
rb_raise(rb_path2class("JSON::ParserError"),
|
121
|
-
"
|
121
|
+
"\\uXXXX is illegal/malformed utf-16 near %s", source);
|
122
122
|
}
|
123
123
|
}
|
124
124
|
/* Figure out how many bytes the result will require */
|
data/lib/json/common.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'json/version'
|
2
|
+
require 'iconv'
|
2
3
|
|
3
4
|
module JSON
|
4
5
|
class << self
|
@@ -74,7 +75,7 @@ module JSON
|
|
74
75
|
end
|
75
76
|
self.create_id = 'json_class'
|
76
77
|
|
77
|
-
NaN =
|
78
|
+
NaN = 0.0/0
|
78
79
|
|
79
80
|
Infinity = 1.0/0
|
80
81
|
|
@@ -105,7 +106,7 @@ module JSON
|
|
105
106
|
|
106
107
|
module_function
|
107
108
|
|
108
|
-
# Parse the JSON
|
109
|
+
# Parse the JSON document _source_ into a Ruby data structure and return it.
|
109
110
|
#
|
110
111
|
# _opts_ can have the following
|
111
112
|
# keys:
|
@@ -122,9 +123,9 @@ module JSON
|
|
122
123
|
JSON.parser.new(source, opts).parse
|
123
124
|
end
|
124
125
|
|
125
|
-
# Parse the JSON
|
126
|
+
# Parse the JSON document _source_ into a Ruby data structure and return it.
|
126
127
|
# The bang version of the parse method, defaults to the more dangerous values
|
127
|
-
# for the _opts_ hash, so be sure only to parse trusted _source_
|
128
|
+
# for the _opts_ hash, so be sure only to parse trusted _source_ documents.
|
128
129
|
#
|
129
130
|
# _opts_ can have the following keys:
|
130
131
|
# * *max_nesting*: The maximum depth of nesting allowed in the parsed data
|
@@ -145,9 +146,8 @@ module JSON
|
|
145
146
|
JSON.parser.new(source, opts).parse
|
146
147
|
end
|
147
148
|
|
148
|
-
#
|
149
|
-
#
|
150
|
-
# * a JSON::State object,
|
149
|
+
# Generate a JSON document from the Ruby data structure _obj_ and return
|
150
|
+
# it. _state_ is * a JSON::State object,
|
151
151
|
# * or a Hash like object (responding to to_hash),
|
152
152
|
# * an object convertible into a hash by a to_h method,
|
153
153
|
# that is used as or to configure a State object.
|
@@ -180,7 +180,11 @@ module JSON
|
|
180
180
|
else
|
181
181
|
state = State.new
|
182
182
|
end
|
183
|
-
obj.to_json(state)
|
183
|
+
result = obj.to_json(state)
|
184
|
+
if result !~ /\A\s*(?:\[.*\]|\{.*\})\s*\Z/m
|
185
|
+
raise GeneratorError, "only generation of JSON objects or arrays allowed"
|
186
|
+
end
|
187
|
+
result
|
184
188
|
end
|
185
189
|
|
186
190
|
# :stopdoc:
|
@@ -190,14 +194,17 @@ module JSON
|
|
190
194
|
module_function :unparse
|
191
195
|
# :startdoc:
|
192
196
|
|
193
|
-
#
|
194
|
-
#
|
195
|
-
# also generates NaN, Infinity, and, -Infinity float values.
|
197
|
+
# Generate a JSON document from the Ruby data structure _obj_ and return it.
|
198
|
+
# This method disables the checks for circles in Ruby objects.
|
196
199
|
#
|
197
200
|
# *WARNING*: Be careful not to pass any Ruby data structures with circles as
|
198
201
|
# _obj_ argument, because this will cause JSON to go into an infinite loop.
|
199
202
|
def fast_generate(obj)
|
200
|
-
obj.to_json(nil)
|
203
|
+
result = obj.to_json(nil)
|
204
|
+
if result !~ /\A(?:\[.*\]|\{.*\})\Z/
|
205
|
+
raise GeneratorError, "only generation of JSON objects or arrays allowed"
|
206
|
+
end
|
207
|
+
result
|
201
208
|
end
|
202
209
|
|
203
210
|
# :stopdoc:
|
@@ -206,8 +213,9 @@ module JSON
|
|
206
213
|
module_function :fast_unparse
|
207
214
|
# :startdoc:
|
208
215
|
|
209
|
-
#
|
210
|
-
# returned
|
216
|
+
# Generate a JSON document from the Ruby data structure _obj_ and return it.
|
217
|
+
# The returned document is a prettier form of the document returned by
|
218
|
+
# #unparse.
|
211
219
|
#
|
212
220
|
# The _opts_ argument can be used to configure the generator, see the
|
213
221
|
# generate method for a more detailed explanation.
|
@@ -229,7 +237,11 @@ module JSON
|
|
229
237
|
end
|
230
238
|
state.configure(opts)
|
231
239
|
end
|
232
|
-
obj.to_json(state)
|
240
|
+
result = obj.to_json(state)
|
241
|
+
if result !~ /\A\s*(?:\[.*\]|\{.*\})\s*\Z/m
|
242
|
+
raise GeneratorError, "only generation of JSON objects or arrays allowed"
|
243
|
+
end
|
244
|
+
result
|
233
245
|
end
|
234
246
|
|
235
247
|
# :stopdoc:
|
@@ -270,8 +282,6 @@ module JSON
|
|
270
282
|
proc.call result
|
271
283
|
end
|
272
284
|
end
|
273
|
-
private :recurse_proc
|
274
|
-
module_function :recurse_proc
|
275
285
|
|
276
286
|
alias restore load
|
277
287
|
module_function :restore
|
@@ -307,6 +317,11 @@ module JSON
|
|
307
317
|
rescue JSON::NestingError
|
308
318
|
raise ArgumentError, "exceed depth limit"
|
309
319
|
end
|
320
|
+
|
321
|
+
# Shortuct for iconv.
|
322
|
+
def self.iconv(to, from, string)
|
323
|
+
Iconv.iconv(to, from, string).first
|
324
|
+
end
|
310
325
|
end
|
311
326
|
|
312
327
|
module ::Kernel
|
data/lib/json/pure/generator.rb
CHANGED
@@ -38,11 +38,11 @@ module JSON
|
|
38
38
|
|
39
39
|
# Convert a UTF8 encoded Ruby string _string_ to a JSON string, encoded with
|
40
40
|
# UTF16 big endian characters as \u????, and return it.
|
41
|
-
if
|
41
|
+
if defined?(::Encoding)
|
42
42
|
def utf8_to_json(string) # :nodoc:
|
43
43
|
string = string.dup
|
44
44
|
string << '' # XXX workaround: avoid buffer sharing
|
45
|
-
string.force_encoding(Encoding::ASCII_8BIT)
|
45
|
+
string.force_encoding(::Encoding::ASCII_8BIT)
|
46
46
|
string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] }
|
47
47
|
string.gsub!(/(
|
48
48
|
(?:
|
@@ -56,7 +56,7 @@ module JSON
|
|
56
56
|
s = JSON::UTF8toUTF16.iconv(c).unpack('H*')[0]
|
57
57
|
s.gsub!(/.{4}/n, '\\\\u\&')
|
58
58
|
}
|
59
|
-
string.force_encoding(Encoding::UTF_8)
|
59
|
+
string.force_encoding(::Encoding::UTF_8)
|
60
60
|
string
|
61
61
|
rescue Iconv::Failure => e
|
62
62
|
raise GeneratorError, "Caught #{e.class}: #{e}"
|
@@ -351,13 +351,13 @@ module JSON
|
|
351
351
|
def to_json(state = nil, *)
|
352
352
|
case
|
353
353
|
when infinite?
|
354
|
-
if
|
354
|
+
if state && state.allow_nan?
|
355
355
|
to_s
|
356
356
|
else
|
357
357
|
raise GeneratorError, "#{self} not allowed in JSON"
|
358
358
|
end
|
359
359
|
when nan?
|
360
|
-
if
|
360
|
+
if state && state.allow_nan?
|
361
361
|
to_s
|
362
362
|
else
|
363
363
|
raise GeneratorError, "#{self} not allowed in JSON"
|
@@ -369,11 +369,25 @@ module JSON
|
|
369
369
|
end
|
370
370
|
|
371
371
|
module String
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
372
|
+
if defined?(::Encoding)
|
373
|
+
# This string should be encoded with UTF-8 A call to this method
|
374
|
+
# returns a JSON string encoded with UTF16 big endian characters as
|
375
|
+
# \u????.
|
376
|
+
def to_json(*)
|
377
|
+
if encoding == ::Encoding::UTF_8
|
378
|
+
'"' << JSON.utf8_to_json(self) << '"'
|
379
|
+
else
|
380
|
+
string = encode(::Encoding::UTF_8)
|
381
|
+
'"' << JSON.utf8_to_json(string) << '"'
|
382
|
+
end
|
383
|
+
end
|
384
|
+
else
|
385
|
+
# This string should be encoded with UTF-8 A call to this method
|
386
|
+
# returns a JSON string encoded with UTF16 big endian characters as
|
387
|
+
# \u????.
|
388
|
+
def to_json(*)
|
389
|
+
'"' << JSON.utf8_to_json(self) << '"'
|
390
|
+
end
|
377
391
|
end
|
378
392
|
|
379
393
|
# Module that holds the extinding methods if, the String module is
|
data/lib/json/pure/parser.rb
CHANGED
@@ -66,7 +66,41 @@ module JSON
|
|
66
66
|
# * *object_class*: Defaults to Hash
|
67
67
|
# * *array_class*: Defaults to Array
|
68
68
|
def initialize(source, opts = {})
|
69
|
-
|
69
|
+
if defined?(::Encoding)
|
70
|
+
if source.encoding == Encoding::ASCII_8BIT
|
71
|
+
b = source[0, 4].bytes.to_a
|
72
|
+
source = case
|
73
|
+
when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
|
74
|
+
source.dup.force_encoding(Encoding::UTF_32BE).encode!(Encoding::UTF_8)
|
75
|
+
when b.size >= 4 && b[0] == 0 && b[2] == 0
|
76
|
+
source.dup.force_encoding(Encoding::UTF_16BE).encode!(Encoding::UTF_8)
|
77
|
+
when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
|
78
|
+
source.dup.force_encoding(Encoding::UTF_32LE).encode!(Encoding::UTF_8)
|
79
|
+
when b.size >= 4 && b[1] == 0 && b[3] == 0
|
80
|
+
source.dup.force_encoding(Encoding::UTF_16LE).encode!(Encoding::UTF_8)
|
81
|
+
else
|
82
|
+
source.dup
|
83
|
+
end
|
84
|
+
else
|
85
|
+
source = source.encode(Encoding::UTF_8)
|
86
|
+
end
|
87
|
+
source.force_encoding(Encoding::ASCII_8BIT)
|
88
|
+
else
|
89
|
+
b = source
|
90
|
+
source = case
|
91
|
+
when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
|
92
|
+
JSON.iconv('utf-8', 'utf-32be', b)
|
93
|
+
when b.size >= 4 && b[0] == 0 && b[2] == 0
|
94
|
+
JSON.iconv('utf-8', 'utf-16be', b)
|
95
|
+
when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
|
96
|
+
JSON.iconv('utf-8', 'utf-32le', b)
|
97
|
+
when b.size >= 4 && b[1] == 0 && b[3] == 0
|
98
|
+
JSON.iconv('utf-8', 'utf-16le', b)
|
99
|
+
else
|
100
|
+
b
|
101
|
+
end
|
102
|
+
end
|
103
|
+
super source
|
70
104
|
if !opts.key?(:max_nesting) # defaults to 19
|
71
105
|
@max_nesting = 19
|
72
106
|
elsif opts[:max_nesting]
|
data/lib/json/version.rb
CHANGED
data/tests/test_json.rb
CHANGED
@@ -9,6 +9,20 @@ else require 'json'
|
|
9
9
|
end
|
10
10
|
require 'stringio'
|
11
11
|
|
12
|
+
unless Array.method_defined?(:permutation)
|
13
|
+
begin
|
14
|
+
require 'enumerator'
|
15
|
+
require 'permutation'
|
16
|
+
class Array
|
17
|
+
def permutation
|
18
|
+
Permutation.for(self).to_enum.map { |x| x.project }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
rescue LoadError
|
22
|
+
warn "Skipping permutation tests."
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
12
26
|
class TC_JSON < Test::Unit::TestCase
|
13
27
|
include JSON
|
14
28
|
|
@@ -94,30 +108,24 @@ class TC_JSON < Test::Unit::TestCase
|
|
94
108
|
assert_equal({ "a" => 0.23 }, parse(' { "a" : 0.23 } '))
|
95
109
|
end
|
96
110
|
|
97
|
-
|
98
|
-
require 'permutation'
|
111
|
+
if Array.method_defined?(:permutation)
|
99
112
|
def test_parse_more_complex_arrays
|
100
113
|
a = [ nil, false, true, "foßbar", [ "n€st€d", true ], { "nested" => true, "n€ßt€ð2" => {} }]
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
json = pretty_generate(orig_ary)
|
105
|
-
assert_equal orig_ary, parse(json)
|
114
|
+
a.permutation.each do |perm|
|
115
|
+
json = pretty_generate(perm)
|
116
|
+
assert_equal perm, parse(json)
|
106
117
|
end
|
107
118
|
end
|
108
119
|
|
109
120
|
def test_parse_complex_objects
|
110
121
|
a = [ nil, false, true, "foßbar", [ "n€st€d", true ], { "nested" => true, "n€ßt€ð2" => {} }]
|
111
|
-
|
112
|
-
perms.each do |perm|
|
122
|
+
a.permutation.each do |perm|
|
113
123
|
s = "a"
|
114
|
-
orig_obj = perm.
|
124
|
+
orig_obj = perm.inject({}) { |h, x| h[s.dup] = x; s = s.succ; h }
|
115
125
|
json = pretty_generate(orig_obj)
|
116
126
|
assert_equal orig_obj, parse(json)
|
117
127
|
end
|
118
128
|
end
|
119
|
-
rescue LoadError
|
120
|
-
warn "Skipping permutation tests."
|
121
129
|
end
|
122
130
|
|
123
131
|
def test_parse_arrays
|
@@ -222,27 +230,27 @@ EOT
|
|
222
230
|
def test_backslash
|
223
231
|
data = [ '\\.(?i:gif|jpe?g|png)$' ]
|
224
232
|
json = '["\\\\.(?i:gif|jpe?g|png)$"]'
|
225
|
-
assert_equal json, JSON.
|
233
|
+
assert_equal json, JSON.generate(data)
|
226
234
|
assert_equal data, JSON.parse(json)
|
227
235
|
#
|
228
236
|
data = [ '\\"' ]
|
229
237
|
json = '["\\\\\""]'
|
230
|
-
assert_equal json, JSON.
|
238
|
+
assert_equal json, JSON.generate(data)
|
231
239
|
assert_equal data, JSON.parse(json)
|
232
240
|
#
|
233
241
|
json = '["/"]'
|
234
242
|
data = JSON.parse(json)
|
235
243
|
assert_equal ['/'], data
|
236
|
-
assert_equal json, JSON.
|
244
|
+
assert_equal json, JSON.generate(data)
|
237
245
|
#
|
238
246
|
json = '["\""]'
|
239
247
|
data = JSON.parse(json)
|
240
248
|
assert_equal ['"'], data
|
241
|
-
assert_equal json, JSON.
|
249
|
+
assert_equal json, JSON.generate(data)
|
242
250
|
json = '["\\\'"]'
|
243
251
|
data = JSON.parse(json)
|
244
252
|
assert_equal ["'"], data
|
245
|
-
assert_equal '["\'"]', JSON.
|
253
|
+
assert_equal '["\'"]', JSON.generate(data)
|
246
254
|
end
|
247
255
|
|
248
256
|
def test_wrong_inputs
|