json_pure 1.1.9 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|