json_pure 2.0.4 → 2.4.0
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 +5 -5
- data/.gitignore +1 -0
- data/.travis.yml +9 -5
- data/CHANGES.md +39 -0
- data/Gemfile +1 -3
- data/LICENSE +56 -0
- data/README.md +54 -21
- data/Rakefile +19 -93
- data/VERSION +1 -1
- data/ext/json/ext/generator/generator.c +214 -45
- data/ext/json/ext/generator/generator.h +5 -2
- data/ext/json/ext/parser/extconf.rb +25 -0
- data/ext/json/ext/parser/parser.c +155 -83
- data/ext/json/ext/parser/parser.h +2 -0
- data/ext/json/ext/parser/parser.rl +79 -7
- data/ext/json/extconf.rb +1 -0
- data/java/src/json/ext/Generator.java +28 -24
- data/java/src/json/ext/GeneratorState.java +30 -0
- data/java/src/json/ext/Parser.java +109 -82
- data/java/src/json/ext/Parser.rl +39 -12
- data/java/src/json/ext/StringEncoder.java +8 -2
- data/json-java.gemspec +22 -22
- data/json.gemspec +0 -0
- data/json_pure.gemspec +9 -14
- data/lib/json.rb +549 -29
- data/lib/json/add/bigdecimal.rb +2 -2
- data/lib/json/add/complex.rb +2 -3
- data/lib/json/add/ostruct.rb +1 -1
- data/lib/json/add/rational.rb +2 -3
- data/lib/json/add/regexp.rb +2 -2
- data/lib/json/add/set.rb +29 -0
- data/lib/json/common.rb +341 -115
- data/lib/json/pure/generator.rb +31 -10
- data/lib/json/pure/parser.rb +35 -5
- data/lib/json/version.rb +1 -1
- data/tests/json_addition_test.rb +6 -0
- data/tests/json_common_interface_test.rb +47 -4
- data/tests/json_encoding_test.rb +2 -2
- data/tests/json_fixtures_test.rb +9 -1
- data/tests/json_generator_test.rb +55 -0
- data/tests/json_parser_test.rb +43 -12
- data/tests/test_helper.rb +3 -7
- metadata +17 -13
- data/data/example.json +0 -1
- data/data/index.html +0 -38
- data/data/prototype.js +0 -4184
data/lib/json/pure/generator.rb
CHANGED
@@ -37,20 +37,26 @@ module JSON
|
|
37
37
|
'\\' => '\\\\',
|
38
38
|
} # :nodoc:
|
39
39
|
|
40
|
+
ESCAPE_SLASH_MAP = MAP.merge(
|
41
|
+
'/' => '\\/',
|
42
|
+
)
|
43
|
+
|
40
44
|
# Convert a UTF8 encoded Ruby string _string_ to a JSON string, encoded with
|
41
45
|
# UTF16 big endian characters as \u????, and return it.
|
42
|
-
def utf8_to_json(string) # :nodoc:
|
46
|
+
def utf8_to_json(string, escape_slash = false) # :nodoc:
|
43
47
|
string = string.dup
|
44
48
|
string.force_encoding(::Encoding::ASCII_8BIT)
|
45
|
-
|
49
|
+
map = escape_slash ? ESCAPE_SLASH_MAP : MAP
|
50
|
+
string.gsub!(/[\/"\\\x0-\x1f]/) { map[$&] || $& }
|
46
51
|
string.force_encoding(::Encoding::UTF_8)
|
47
52
|
string
|
48
53
|
end
|
49
54
|
|
50
|
-
def utf8_to_json_ascii(string) # :nodoc:
|
55
|
+
def utf8_to_json_ascii(string, escape_slash = false) # :nodoc:
|
51
56
|
string = string.dup
|
52
57
|
string.force_encoding(::Encoding::ASCII_8BIT)
|
53
|
-
|
58
|
+
map = escape_slash ? ESCAPE_SLASH_MAP : MAP
|
59
|
+
string.gsub!(/[\/"\\\x0-\x1f]/n) { map[$&] || $& }
|
54
60
|
string.gsub!(/(
|
55
61
|
(?:
|
56
62
|
[\xc2-\xdf][\x80-\xbf] |
|
@@ -109,6 +115,7 @@ module JSON
|
|
109
115
|
# * *space_before*: a string that is put before a : pair delimiter (default: ''),
|
110
116
|
# * *object_nl*: a string that is put at the end of a JSON object (default: ''),
|
111
117
|
# * *array_nl*: a string that is put at the end of a JSON array (default: ''),
|
118
|
+
# * *escape_slash*: true if forward slash (/) should be escaped (default: false)
|
112
119
|
# * *check_circular*: is deprecated now, use the :max_nesting option instead,
|
113
120
|
# * *max_nesting*: sets the maximum level of data structure nesting in
|
114
121
|
# the generated JSON, max_nesting = 0 if no maximum should be checked.
|
@@ -123,6 +130,7 @@ module JSON
|
|
123
130
|
@array_nl = ''
|
124
131
|
@allow_nan = false
|
125
132
|
@ascii_only = false
|
133
|
+
@escape_slash = false
|
126
134
|
@buffer_initial_length = 1024
|
127
135
|
configure opts
|
128
136
|
end
|
@@ -148,6 +156,10 @@ module JSON
|
|
148
156
|
# the generated JSON, max_nesting = 0 if no maximum is checked.
|
149
157
|
attr_accessor :max_nesting
|
150
158
|
|
159
|
+
# If this attribute is set to true, forward slashes will be escaped in
|
160
|
+
# all json strings.
|
161
|
+
attr_accessor :escape_slash
|
162
|
+
|
151
163
|
# :stopdoc:
|
152
164
|
attr_reader :buffer_initial_length
|
153
165
|
|
@@ -187,6 +199,11 @@ module JSON
|
|
187
199
|
@ascii_only
|
188
200
|
end
|
189
201
|
|
202
|
+
# Returns true, if forward slashes are escaped. Otherwise returns false.
|
203
|
+
def escape_slash?
|
204
|
+
@escape_slash
|
205
|
+
end
|
206
|
+
|
190
207
|
# Configure this State instance with the Hash _opts_, and return
|
191
208
|
# itself.
|
192
209
|
def configure(opts)
|
@@ -209,6 +226,7 @@ module JSON
|
|
209
226
|
@ascii_only = opts[:ascii_only] if opts.key?(:ascii_only)
|
210
227
|
@depth = opts[:depth] || 0
|
211
228
|
@buffer_initial_length ||= opts[:buffer_initial_length]
|
229
|
+
@escape_slash = !!opts[:escape_slash] if opts.key?(:escape_slash)
|
212
230
|
|
213
231
|
if !opts.key?(:max_nesting) # defaults to 100
|
214
232
|
@max_nesting = 100
|
@@ -250,7 +268,8 @@ module JSON
|
|
250
268
|
if respond_to?(name)
|
251
269
|
__send__(name)
|
252
270
|
else
|
253
|
-
instance_variable_get("@#{name}")
|
271
|
+
instance_variable_get("@#{name}") if
|
272
|
+
instance_variables.include?("@#{name}".to_sym) # avoid warning
|
254
273
|
end
|
255
274
|
end
|
256
275
|
|
@@ -313,8 +332,10 @@ module JSON
|
|
313
332
|
first = false
|
314
333
|
}
|
315
334
|
depth = state.depth -= 1
|
316
|
-
|
317
|
-
|
335
|
+
unless first
|
336
|
+
result << state.object_nl
|
337
|
+
result << state.indent * depth if indent
|
338
|
+
end
|
318
339
|
result << '}'
|
319
340
|
result
|
320
341
|
end
|
@@ -398,13 +419,13 @@ module JSON
|
|
398
419
|
string = encode(::Encoding::UTF_8)
|
399
420
|
end
|
400
421
|
if state.ascii_only?
|
401
|
-
'"' << JSON.utf8_to_json_ascii(string) << '"'
|
422
|
+
'"' << JSON.utf8_to_json_ascii(string, state.escape_slash) << '"'
|
402
423
|
else
|
403
|
-
'"' << JSON.utf8_to_json(string) << '"'
|
424
|
+
'"' << JSON.utf8_to_json(string, state.escape_slash) << '"'
|
404
425
|
end
|
405
426
|
end
|
406
427
|
|
407
|
-
# Module that holds the
|
428
|
+
# Module that holds the extending methods if, the String module is
|
408
429
|
# included.
|
409
430
|
module Extend
|
410
431
|
# Raw Strings are JSON Objects (the raw bytes are stored in an
|
data/lib/json/pure/parser.rb
CHANGED
@@ -49,7 +49,7 @@ module JSON
|
|
49
49
|
)+
|
50
50
|
)mx
|
51
51
|
|
52
|
-
|
52
|
+
UNPARSED = Object.new.freeze
|
53
53
|
|
54
54
|
# Creates a new JSON::Pure::Parser instance for the string _source_.
|
55
55
|
#
|
@@ -61,15 +61,20 @@ module JSON
|
|
61
61
|
# * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
|
62
62
|
# defiance of RFC 7159 to be parsed by the Parser. This option defaults
|
63
63
|
# to false.
|
64
|
+
# * *freeze*: If set to true, all parsed objects will be frozen. Parsed
|
65
|
+
# string will be deduplicated if possible.
|
64
66
|
# * *symbolize_names*: If set to true, returns symbols for the names
|
65
67
|
# (keys) in a JSON object. Otherwise strings are returned, which is
|
66
68
|
# also the default. It's not possible to use this option in
|
67
69
|
# conjunction with the *create_additions* option.
|
68
70
|
# * *create_additions*: If set to true, the Parser creates
|
69
|
-
# additions when
|
71
|
+
# additions when a matching class and create_id are found. This
|
70
72
|
# option defaults to false.
|
71
73
|
# * *object_class*: Defaults to Hash
|
72
74
|
# * *array_class*: Defaults to Array
|
75
|
+
# * *decimal_class*: Specifies which class to use instead of the default
|
76
|
+
# (Float) when parsing decimal numbers. This class must accept a single
|
77
|
+
# string argument in its constructor.
|
73
78
|
def initialize(source, opts = {})
|
74
79
|
opts ||= {}
|
75
80
|
source = convert_encoding source
|
@@ -83,6 +88,7 @@ module JSON
|
|
83
88
|
end
|
84
89
|
@allow_nan = !!opts[:allow_nan]
|
85
90
|
@symbolize_names = !!opts[:symbolize_names]
|
91
|
+
@freeze = !!opts[:freeze]
|
86
92
|
if opts.key?(:create_additions)
|
87
93
|
@create_additions = !!opts[:create_additions]
|
88
94
|
else
|
@@ -94,6 +100,7 @@ module JSON
|
|
94
100
|
@create_id = @create_additions ? JSON.create_id : nil
|
95
101
|
@object_class = opts[:object_class] || Hash
|
96
102
|
@array_class = opts[:array_class] || Array
|
103
|
+
@decimal_class = opts[:decimal_class]
|
97
104
|
@match_string = opts[:match_string]
|
98
105
|
end
|
99
106
|
|
@@ -116,6 +123,7 @@ module JSON
|
|
116
123
|
obj = parse_value
|
117
124
|
UNPARSED.equal?(obj) and raise ParserError,
|
118
125
|
"source is not valid JSON!"
|
126
|
+
obj.freeze if @freeze
|
119
127
|
end
|
120
128
|
while !eos? && skip(IGNORE) do end
|
121
129
|
eos? or raise ParserError, "source is not valid JSON!"
|
@@ -157,6 +165,7 @@ module JSON
|
|
157
165
|
EMPTY_8BIT_STRING.force_encoding Encoding::ASCII_8BIT
|
158
166
|
end
|
159
167
|
|
168
|
+
STR_UMINUS = ''.respond_to?(:-@)
|
160
169
|
def parse_string
|
161
170
|
if scan(STRING)
|
162
171
|
return '' if self[1].empty?
|
@@ -176,6 +185,15 @@ module JSON
|
|
176
185
|
if string.respond_to?(:force_encoding)
|
177
186
|
string.force_encoding(::Encoding::UTF_8)
|
178
187
|
end
|
188
|
+
|
189
|
+
if @freeze
|
190
|
+
if STR_UMINUS
|
191
|
+
string = -string
|
192
|
+
else
|
193
|
+
string.freeze
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
179
197
|
if @create_additions and @match_string
|
180
198
|
for (regexp, klass) in @match_string
|
181
199
|
klass.json_creatable? or next
|
@@ -193,7 +211,15 @@ module JSON
|
|
193
211
|
def parse_value
|
194
212
|
case
|
195
213
|
when scan(FLOAT)
|
196
|
-
|
214
|
+
if @decimal_class then
|
215
|
+
if @decimal_class == BigDecimal then
|
216
|
+
BigDecimal(self[1])
|
217
|
+
else
|
218
|
+
@decimal_class.new(self[1]) || Float(self[1])
|
219
|
+
end
|
220
|
+
else
|
221
|
+
Float(self[1])
|
222
|
+
end
|
197
223
|
when scan(INTEGER)
|
198
224
|
Integer(self[1])
|
199
225
|
when scan(TRUE)
|
@@ -230,8 +256,10 @@ module JSON
|
|
230
256
|
@max_nesting.nonzero? && @current_nesting > @max_nesting
|
231
257
|
result = @array_class.new
|
232
258
|
delim = false
|
233
|
-
|
259
|
+
loop do
|
234
260
|
case
|
261
|
+
when eos?
|
262
|
+
raise ParserError, "unexpected end of string while parsing array"
|
235
263
|
when !UNPARSED.equal?(value = parse_value)
|
236
264
|
delim = false
|
237
265
|
result << value
|
@@ -262,8 +290,10 @@ module JSON
|
|
262
290
|
@max_nesting.nonzero? && @current_nesting > @max_nesting
|
263
291
|
result = @object_class.new
|
264
292
|
delim = false
|
265
|
-
|
293
|
+
loop do
|
266
294
|
case
|
295
|
+
when eos?
|
296
|
+
raise ParserError, "unexpected end of string while parsing object"
|
267
297
|
when !UNPARSED.equal?(string = parse_string)
|
268
298
|
skip(IGNORE)
|
269
299
|
unless scan(PAIR_DELIMITER)
|
data/lib/json/version.rb
CHANGED
data/tests/json_addition_test.rb
CHANGED
@@ -5,6 +5,7 @@ require 'json/add/complex'
|
|
5
5
|
require 'json/add/rational'
|
6
6
|
require 'json/add/bigdecimal'
|
7
7
|
require 'json/add/ostruct'
|
8
|
+
require 'json/add/set'
|
8
9
|
require 'date'
|
9
10
|
|
10
11
|
class JSONAdditionTest < Test::Unit::TestCase
|
@@ -190,4 +191,9 @@ class JSONAdditionTest < Test::Unit::TestCase
|
|
190
191
|
o.foo = { 'bar' => true }
|
191
192
|
assert_equal o, parse(JSON(o), :create_additions => true)
|
192
193
|
end
|
194
|
+
|
195
|
+
def test_set
|
196
|
+
s = Set.new([:a, :b, :c, :a])
|
197
|
+
assert_equal s, JSON.parse(JSON(s), :create_additions => true)
|
198
|
+
end
|
193
199
|
end
|
@@ -27,15 +27,15 @@ class JSONCommonInterfaceTest < Test::Unit::TestCase
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def test_parser
|
30
|
-
assert_match
|
30
|
+
assert_match(/::Parser\z/, JSON.parser.name)
|
31
31
|
end
|
32
32
|
|
33
33
|
def test_generator
|
34
|
-
assert_match
|
34
|
+
assert_match(/::Generator\z/, JSON.generator.name)
|
35
35
|
end
|
36
36
|
|
37
37
|
def test_state
|
38
|
-
assert_match
|
38
|
+
assert_match(/::Generator::State\z/, JSON.state.name)
|
39
39
|
end
|
40
40
|
|
41
41
|
def test_create_id
|
@@ -56,7 +56,7 @@ class JSONCommonInterfaceTest < Test::Unit::TestCase
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def test_parse_bang
|
59
|
-
assert_equal [ 1,
|
59
|
+
assert_equal [ 1, Infinity, 3, ], JSON.parse!('[ 1, Infinity, 3 ]')
|
60
60
|
end
|
61
61
|
|
62
62
|
def test_generate
|
@@ -123,4 +123,47 @@ class JSONCommonInterfaceTest < Test::Unit::TestCase
|
|
123
123
|
assert_equal @json, JSON(@hash)
|
124
124
|
assert_equal @hash, JSON(@json)
|
125
125
|
end
|
126
|
+
|
127
|
+
def test_load_file
|
128
|
+
test_load_shared(:load_file)
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_load_file!
|
132
|
+
test_load_shared(:load_file!)
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_load_file_with_option
|
136
|
+
test_load_file_with_option_shared(:load_file)
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_load_file_with_option!
|
140
|
+
test_load_file_with_option_shared(:load_file!)
|
141
|
+
end
|
142
|
+
|
143
|
+
private
|
144
|
+
|
145
|
+
def test_load_shared(method_name)
|
146
|
+
temp_file_containing(@json) do |filespec|
|
147
|
+
assert_equal JSON.public_send(method_name, filespec), @hash
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def test_load_file_with_option_shared(method_name)
|
152
|
+
temp_file_containing(@json) do |filespec|
|
153
|
+
parsed_object = JSON.public_send(method_name, filespec, symbolize_names: true)
|
154
|
+
key_classes = parsed_object.keys.map(&:class)
|
155
|
+
assert_include(key_classes, Symbol)
|
156
|
+
assert_not_include(key_classes, String)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def temp_file_containing(text, file_prefix = '')
|
161
|
+
raise "This method must be called with a code block." unless block_given?
|
162
|
+
|
163
|
+
Tempfile.create(file_prefix) do |file|
|
164
|
+
file << text
|
165
|
+
file.close
|
166
|
+
yield file.path
|
167
|
+
end
|
168
|
+
end
|
126
169
|
end
|
data/tests/json_encoding_test.rb
CHANGED
@@ -79,8 +79,8 @@ class JSONEncodingTest < Test::Unit::TestCase
|
|
79
79
|
json = '["\ud840\udc01"]'
|
80
80
|
assert_equal json, generate(utf8, :ascii_only => true)
|
81
81
|
assert_equal utf8, parse(json)
|
82
|
-
|
83
|
-
|
82
|
+
assert_raise(JSON::ParserError) { parse('"\u"') }
|
83
|
+
assert_raise(JSON::ParserError) { parse('"\ud800"') }
|
84
84
|
end
|
85
85
|
|
86
86
|
def test_chars
|
data/tests/json_fixtures_test.rb
CHANGED
@@ -3,13 +3,14 @@ require 'test_helper'
|
|
3
3
|
|
4
4
|
class JSONFixturesTest < Test::Unit::TestCase
|
5
5
|
def setup
|
6
|
-
fixtures = File.join(File.dirname(__FILE__), 'fixtures/{fail,pass}
|
6
|
+
fixtures = File.join(File.dirname(__FILE__), 'fixtures/{fail,pass}*.json')
|
7
7
|
passed, failed = Dir[fixtures].partition { |f| f['pass'] }
|
8
8
|
@passed = passed.inject([]) { |a, f| a << [ f, File.read(f) ] }.sort
|
9
9
|
@failed = failed.inject([]) { |a, f| a << [ f, File.read(f) ] }.sort
|
10
10
|
end
|
11
11
|
|
12
12
|
def test_passing
|
13
|
+
verbose_bak, $VERBOSE = $VERBOSE, nil
|
13
14
|
for name, source in @passed
|
14
15
|
begin
|
15
16
|
assert JSON.parse(source),
|
@@ -19,6 +20,8 @@ class JSONFixturesTest < Test::Unit::TestCase
|
|
19
20
|
raise e
|
20
21
|
end
|
21
22
|
end
|
23
|
+
ensure
|
24
|
+
$VERBOSE = verbose_bak
|
22
25
|
end
|
23
26
|
|
24
27
|
def test_failing
|
@@ -29,4 +32,9 @@ class JSONFixturesTest < Test::Unit::TestCase
|
|
29
32
|
end
|
30
33
|
end
|
31
34
|
end
|
35
|
+
|
36
|
+
def test_sanity
|
37
|
+
assert(@passed.size > 5)
|
38
|
+
assert(@failed.size > 20)
|
39
|
+
end
|
32
40
|
end
|
@@ -40,6 +40,43 @@ class JSONGeneratorTest < Test::Unit::TestCase
|
|
40
40
|
EOT
|
41
41
|
end
|
42
42
|
|
43
|
+
def silence
|
44
|
+
v = $VERBOSE
|
45
|
+
$VERBOSE = nil
|
46
|
+
yield
|
47
|
+
ensure
|
48
|
+
$VERBOSE = v
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_remove_const_segv
|
52
|
+
stress = GC.stress
|
53
|
+
const = JSON::SAFE_STATE_PROTOTYPE.dup
|
54
|
+
|
55
|
+
bignum_too_long_to_embed_as_string = 1234567890123456789012345
|
56
|
+
expect = bignum_too_long_to_embed_as_string.to_s
|
57
|
+
GC.stress = true
|
58
|
+
|
59
|
+
10.times do |i|
|
60
|
+
tmp = bignum_too_long_to_embed_as_string.to_json
|
61
|
+
raise "'\#{expect}' is expected, but '\#{tmp}'" unless tmp == expect
|
62
|
+
end
|
63
|
+
|
64
|
+
silence do
|
65
|
+
JSON.const_set :SAFE_STATE_PROTOTYPE, nil
|
66
|
+
end
|
67
|
+
|
68
|
+
10.times do |i|
|
69
|
+
assert_raise TypeError do
|
70
|
+
bignum_too_long_to_embed_as_string.to_json
|
71
|
+
end
|
72
|
+
end
|
73
|
+
ensure
|
74
|
+
GC.stress = stress
|
75
|
+
silence do
|
76
|
+
JSON.const_set :SAFE_STATE_PROTOTYPE, const
|
77
|
+
end
|
78
|
+
end if JSON.const_defined?("Ext") && RUBY_ENGINE != 'jruby'
|
79
|
+
|
43
80
|
def test_generate
|
44
81
|
json = generate(@hash)
|
45
82
|
assert_equal(parse(@json2), parse(json))
|
@@ -55,6 +92,11 @@ EOT
|
|
55
92
|
end
|
56
93
|
|
57
94
|
def test_generate_pretty
|
95
|
+
json = pretty_generate({})
|
96
|
+
assert_equal(<<'EOT'.chomp, json)
|
97
|
+
{
|
98
|
+
}
|
99
|
+
EOT
|
58
100
|
json = pretty_generate(@hash)
|
59
101
|
# hashes aren't (insertion) ordered on every ruby implementation
|
60
102
|
# assert_equal(@json3, json)
|
@@ -136,6 +178,7 @@ EOT
|
|
136
178
|
:ascii_only => false,
|
137
179
|
:buffer_initial_length => 1024,
|
138
180
|
:depth => 0,
|
181
|
+
:escape_slash => false,
|
139
182
|
:indent => " ",
|
140
183
|
:max_nesting => 100,
|
141
184
|
:object_nl => "\n",
|
@@ -152,6 +195,7 @@ EOT
|
|
152
195
|
:ascii_only => false,
|
153
196
|
:buffer_initial_length => 1024,
|
154
197
|
:depth => 0,
|
198
|
+
:escape_slash => false,
|
155
199
|
:indent => "",
|
156
200
|
:max_nesting => 100,
|
157
201
|
:object_nl => "",
|
@@ -168,6 +212,7 @@ EOT
|
|
168
212
|
:ascii_only => false,
|
169
213
|
:buffer_initial_length => 1024,
|
170
214
|
:depth => 0,
|
215
|
+
:escape_slash => false,
|
171
216
|
:indent => "",
|
172
217
|
:max_nesting => 0,
|
173
218
|
:object_nl => "",
|
@@ -356,6 +401,10 @@ EOT
|
|
356
401
|
json = '["/"]'
|
357
402
|
assert_equal json, generate(data)
|
358
403
|
#
|
404
|
+
data = [ '/' ]
|
405
|
+
json = '["\/"]'
|
406
|
+
assert_equal json, generate(data, :escape_slash => true)
|
407
|
+
#
|
359
408
|
data = ['"']
|
360
409
|
json = '["\""]'
|
361
410
|
assert_equal json, generate(data)
|
@@ -374,4 +423,10 @@ EOT
|
|
374
423
|
assert_equal '["foo"]', JSON.generate([s.new('foo')])
|
375
424
|
end
|
376
425
|
end
|
426
|
+
|
427
|
+
if defined?(Encoding)
|
428
|
+
def test_nonutf8_encoding
|
429
|
+
assert_equal("\"5\u{b0}\"", "5\xb0".force_encoding("iso-8859-1").to_json)
|
430
|
+
end
|
431
|
+
end
|
377
432
|
end
|