json 1.1.5-x86-linux

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.

Files changed (117) hide show
  1. data/CHANGES +106 -0
  2. data/GPL +340 -0
  3. data/README +78 -0
  4. data/RUBY +58 -0
  5. data/Rakefile +268 -0
  6. data/TODO +1 -0
  7. data/VERSION +1 -0
  8. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkComparison.log +52 -0
  9. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast-autocorrelation.dat +1000 -0
  10. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast.dat +1001 -0
  11. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty-autocorrelation.dat +900 -0
  12. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty.dat +901 -0
  13. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe-autocorrelation.dat +1000 -0
  14. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe.dat +1001 -0
  15. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt.log +261 -0
  16. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast-autocorrelation.dat +1000 -0
  17. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast.dat +1001 -0
  18. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty-autocorrelation.dat +1000 -0
  19. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty.dat +1001 -0
  20. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe-autocorrelation.dat +1000 -0
  21. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe.dat +1001 -0
  22. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure.log +262 -0
  23. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator-autocorrelation.dat +1000 -0
  24. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator.dat +1001 -0
  25. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails.log +82 -0
  26. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkComparison.log +34 -0
  27. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser-autocorrelation.dat +900 -0
  28. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser.dat +901 -0
  29. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt.log +81 -0
  30. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser-autocorrelation.dat +1000 -0
  31. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser.dat +1001 -0
  32. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure.log +82 -0
  33. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser-autocorrelation.dat +1000 -0
  34. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser.dat +1001 -0
  35. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails.log +82 -0
  36. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser-autocorrelation.dat +1000 -0
  37. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser.dat +1001 -0
  38. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML.log +82 -0
  39. data/benchmarks/generator_benchmark.rb +165 -0
  40. data/benchmarks/parser_benchmark.rb +197 -0
  41. data/bin/edit_json.rb +9 -0
  42. data/bin/prettify_json.rb +75 -0
  43. data/data/example.json +1 -0
  44. data/data/index.html +38 -0
  45. data/data/prototype.js +4184 -0
  46. data/doc-templates/main.txt +283 -0
  47. data/ext/json/ext/generator/extconf.rb +11 -0
  48. data/ext/json/ext/generator/generator.c +919 -0
  49. data/ext/json/ext/generator/unicode.c +182 -0
  50. data/ext/json/ext/generator/unicode.h +53 -0
  51. data/ext/json/ext/parser/extconf.rb +11 -0
  52. data/ext/json/ext/parser/parser.c +1829 -0
  53. data/ext/json/ext/parser/parser.rl +686 -0
  54. data/ext/json/ext/parser/unicode.c +154 -0
  55. data/ext/json/ext/parser/unicode.h +58 -0
  56. data/install.rb +26 -0
  57. data/lib/json.rb +10 -0
  58. data/lib/json/Array.xpm +21 -0
  59. data/lib/json/FalseClass.xpm +21 -0
  60. data/lib/json/Hash.xpm +21 -0
  61. data/lib/json/Key.xpm +73 -0
  62. data/lib/json/NilClass.xpm +21 -0
  63. data/lib/json/Numeric.xpm +28 -0
  64. data/lib/json/String.xpm +96 -0
  65. data/lib/json/TrueClass.xpm +21 -0
  66. data/lib/json/add/core.rb +135 -0
  67. data/lib/json/add/rails.rb +58 -0
  68. data/lib/json/common.rb +354 -0
  69. data/lib/json/editor.rb +1371 -0
  70. data/lib/json/ext.rb +15 -0
  71. data/lib/json/ext/generator.so +0 -0
  72. data/lib/json/ext/parser.so +0 -0
  73. data/lib/json/json.xpm +1499 -0
  74. data/lib/json/pure.rb +77 -0
  75. data/lib/json/pure/generator.rb +430 -0
  76. data/lib/json/pure/parser.rb +267 -0
  77. data/lib/json/version.rb +8 -0
  78. data/tests/fixtures/fail1.json +1 -0
  79. data/tests/fixtures/fail10.json +1 -0
  80. data/tests/fixtures/fail11.json +1 -0
  81. data/tests/fixtures/fail12.json +1 -0
  82. data/tests/fixtures/fail13.json +1 -0
  83. data/tests/fixtures/fail14.json +1 -0
  84. data/tests/fixtures/fail18.json +1 -0
  85. data/tests/fixtures/fail19.json +1 -0
  86. data/tests/fixtures/fail2.json +1 -0
  87. data/tests/fixtures/fail20.json +1 -0
  88. data/tests/fixtures/fail21.json +1 -0
  89. data/tests/fixtures/fail22.json +1 -0
  90. data/tests/fixtures/fail23.json +1 -0
  91. data/tests/fixtures/fail24.json +1 -0
  92. data/tests/fixtures/fail25.json +1 -0
  93. data/tests/fixtures/fail27.json +2 -0
  94. data/tests/fixtures/fail28.json +2 -0
  95. data/tests/fixtures/fail3.json +1 -0
  96. data/tests/fixtures/fail4.json +1 -0
  97. data/tests/fixtures/fail5.json +1 -0
  98. data/tests/fixtures/fail6.json +1 -0
  99. data/tests/fixtures/fail7.json +1 -0
  100. data/tests/fixtures/fail8.json +1 -0
  101. data/tests/fixtures/fail9.json +1 -0
  102. data/tests/fixtures/pass1.json +56 -0
  103. data/tests/fixtures/pass15.json +1 -0
  104. data/tests/fixtures/pass16.json +1 -0
  105. data/tests/fixtures/pass17.json +1 -0
  106. data/tests/fixtures/pass2.json +1 -0
  107. data/tests/fixtures/pass26.json +1 -0
  108. data/tests/fixtures/pass3.json +6 -0
  109. data/tests/test_json.rb +312 -0
  110. data/tests/test_json_addition.rb +164 -0
  111. data/tests/test_json_fixtures.rb +34 -0
  112. data/tests/test_json_generate.rb +106 -0
  113. data/tests/test_json_rails.rb +146 -0
  114. data/tests/test_json_unicode.rb +62 -0
  115. data/tools/fuzz.rb +139 -0
  116. data/tools/server.rb +61 -0
  117. metadata +200 -0
@@ -0,0 +1,267 @@
1
+ require 'strscan'
2
+
3
+ module JSON
4
+ module Pure
5
+ # This class implements the JSON parser that is used to parse a JSON string
6
+ # into a Ruby data structure.
7
+ class Parser < StringScanner
8
+ STRING = /" ((?:[^\x0-\x1f"\\] |
9
+ \\["\\\/bfnrt] |
10
+ \\u[0-9a-fA-F]{4} |
11
+ \\[\x20-\xff])*)
12
+ "/nx
13
+ INTEGER = /(-?0|-?[1-9]\d*)/
14
+ FLOAT = /(-?
15
+ (?:0|[1-9]\d*)
16
+ (?:
17
+ \.\d+(?i:e[+-]?\d+) |
18
+ \.\d+ |
19
+ (?i:e[+-]?\d+)
20
+ )
21
+ )/x
22
+ NAN = /NaN/
23
+ INFINITY = /Infinity/
24
+ MINUS_INFINITY = /-Infinity/
25
+ OBJECT_OPEN = /\{/
26
+ OBJECT_CLOSE = /\}/
27
+ ARRAY_OPEN = /\[/
28
+ ARRAY_CLOSE = /\]/
29
+ PAIR_DELIMITER = /:/
30
+ COLLECTION_DELIMITER = /,/
31
+ TRUE = /true/
32
+ FALSE = /false/
33
+ NULL = /null/
34
+ IGNORE = %r(
35
+ (?:
36
+ //[^\n\r]*[\n\r]| # line comments
37
+ /\* # c-style comments
38
+ (?:
39
+ [^*/]| # normal chars
40
+ /[^*]| # slashes that do not start a nested comment
41
+ \*[^/]| # asterisks that do not end this comment
42
+ /(?=\*/) # single slash before this comment's end
43
+ )*
44
+ \*/ # the End of this comment
45
+ |[ \t\r\n]+ # whitespaces: space, horicontal tab, lf, cr
46
+ )+
47
+ )mx
48
+
49
+ UNPARSED = Object.new
50
+
51
+ # Creates a new JSON::Pure::Parser instance for the string _source_.
52
+ #
53
+ # It will be configured by the _opts_ hash. _opts_ can have the following
54
+ # keys:
55
+ # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
56
+ # structures. Disable depth checking with :max_nesting => false|nil|0,
57
+ # it defaults to 19.
58
+ # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
59
+ # defiance of RFC 4627 to be parsed by the Parser. This option defaults
60
+ # to false.
61
+ # * *create_additions*: If set to false, the Parser doesn't create
62
+ # additions even if a matchin class and create_id was found. This option
63
+ # defaults to true.
64
+ # * *object_class*: Defaults to Hash
65
+ # * *array_class*: Defaults to Array
66
+ def initialize(source, opts = {})
67
+ super
68
+ if !opts.key?(:max_nesting) # defaults to 19
69
+ @max_nesting = 19
70
+ elsif opts[:max_nesting]
71
+ @max_nesting = opts[:max_nesting]
72
+ else
73
+ @max_nesting = 0
74
+ end
75
+ @allow_nan = !!opts[:allow_nan]
76
+ ca = true
77
+ ca = opts[:create_additions] if opts.key?(:create_additions)
78
+ @create_id = ca ? JSON.create_id : nil
79
+ @object_class = opts[:object_class] || Hash
80
+ @array_class = opts[:array_class] || Array
81
+ end
82
+
83
+ alias source string
84
+
85
+ # Parses the current JSON string _source_ and returns the complete data
86
+ # structure as a result.
87
+ def parse
88
+ reset
89
+ obj = nil
90
+ until eos?
91
+ case
92
+ when scan(OBJECT_OPEN)
93
+ obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
94
+ @current_nesting = 1
95
+ obj = parse_object
96
+ when scan(ARRAY_OPEN)
97
+ obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
98
+ @current_nesting = 1
99
+ obj = parse_array
100
+ when skip(IGNORE)
101
+ ;
102
+ else
103
+ raise ParserError, "source '#{peek(20)}' not in JSON!"
104
+ end
105
+ end
106
+ obj or raise ParserError, "source did not contain any JSON!"
107
+ obj
108
+ end
109
+
110
+ private
111
+
112
+ # Unescape characters in strings.
113
+ UNESCAPE_MAP = Hash.new { |h, k| h[k] = k.chr }
114
+ UNESCAPE_MAP.update({
115
+ ?" => '"',
116
+ ?\\ => '\\',
117
+ ?/ => '/',
118
+ ?b => "\b",
119
+ ?f => "\f",
120
+ ?n => "\n",
121
+ ?r => "\r",
122
+ ?t => "\t",
123
+ ?u => nil,
124
+ })
125
+
126
+ def parse_string
127
+ if scan(STRING)
128
+ return '' if self[1].empty?
129
+ string = self[1].gsub(%r((?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))+|\\[\x20-\xff]))n) do |c|
130
+ if u = UNESCAPE_MAP[$&[1]]
131
+ u
132
+ else # \uXXXX
133
+ bytes = ''
134
+ i = 0
135
+ while c[6 * i] == ?\\ && c[6 * i + 1] == ?u
136
+ bytes << c[6 * i + 2, 2].to_i(16) << c[6 * i + 4, 2].to_i(16)
137
+ i += 1
138
+ end
139
+ JSON::UTF16toUTF8.iconv(bytes)
140
+ end
141
+ end
142
+ if string.respond_to?(:force_encoding)
143
+ string.force_encoding(Encoding::UTF_8)
144
+ end
145
+ string
146
+ else
147
+ UNPARSED
148
+ end
149
+ rescue Iconv::Failure => e
150
+ raise GeneratorError, "Caught #{e.class}: #{e}"
151
+ end
152
+
153
+ def parse_value
154
+ case
155
+ when scan(FLOAT)
156
+ Float(self[1])
157
+ when scan(INTEGER)
158
+ Integer(self[1])
159
+ when scan(TRUE)
160
+ true
161
+ when scan(FALSE)
162
+ false
163
+ when scan(NULL)
164
+ nil
165
+ when (string = parse_string) != UNPARSED
166
+ string
167
+ when scan(ARRAY_OPEN)
168
+ @current_nesting += 1
169
+ ary = parse_array
170
+ @current_nesting -= 1
171
+ ary
172
+ when scan(OBJECT_OPEN)
173
+ @current_nesting += 1
174
+ obj = parse_object
175
+ @current_nesting -= 1
176
+ obj
177
+ when @allow_nan && scan(NAN)
178
+ NaN
179
+ when @allow_nan && scan(INFINITY)
180
+ Infinity
181
+ when @allow_nan && scan(MINUS_INFINITY)
182
+ MinusInfinity
183
+ else
184
+ UNPARSED
185
+ end
186
+ end
187
+
188
+ def parse_array
189
+ raise NestingError, "nesting of #@current_nesting is to deep" if
190
+ @max_nesting.nonzero? && @current_nesting > @max_nesting
191
+ result = @array_class.new
192
+ delim = false
193
+ until eos?
194
+ case
195
+ when (value = parse_value) != UNPARSED
196
+ delim = false
197
+ result << value
198
+ skip(IGNORE)
199
+ if scan(COLLECTION_DELIMITER)
200
+ delim = true
201
+ elsif match?(ARRAY_CLOSE)
202
+ ;
203
+ else
204
+ raise ParserError, "expected ',' or ']' in array at '#{peek(20)}'!"
205
+ end
206
+ when scan(ARRAY_CLOSE)
207
+ if delim
208
+ raise ParserError, "expected next element in array at '#{peek(20)}'!"
209
+ end
210
+ break
211
+ when skip(IGNORE)
212
+ ;
213
+ else
214
+ raise ParserError, "unexpected token in array at '#{peek(20)}'!"
215
+ end
216
+ end
217
+ result
218
+ end
219
+
220
+ def parse_object
221
+ raise NestingError, "nesting of #@current_nesting is to deep" if
222
+ @max_nesting.nonzero? && @current_nesting > @max_nesting
223
+ result = @object_class.new
224
+ delim = false
225
+ until eos?
226
+ case
227
+ when (string = parse_string) != UNPARSED
228
+ skip(IGNORE)
229
+ unless scan(PAIR_DELIMITER)
230
+ raise ParserError, "expected ':' in object at '#{peek(20)}'!"
231
+ end
232
+ skip(IGNORE)
233
+ unless (value = parse_value).equal? UNPARSED
234
+ result[string] = value
235
+ delim = false
236
+ skip(IGNORE)
237
+ if scan(COLLECTION_DELIMITER)
238
+ delim = true
239
+ elsif match?(OBJECT_CLOSE)
240
+ ;
241
+ else
242
+ raise ParserError, "expected ',' or '}' in object at '#{peek(20)}'!"
243
+ end
244
+ else
245
+ raise ParserError, "expected value in object at '#{peek(20)}'!"
246
+ end
247
+ when scan(OBJECT_CLOSE)
248
+ if delim
249
+ raise ParserError, "expected next name, value pair in object at '#{peek(20)}'!"
250
+ end
251
+ if @create_id and klassname = result[@create_id]
252
+ klass = JSON.deep_const_get klassname
253
+ break unless klass and klass.json_creatable?
254
+ result = klass.json_create(result)
255
+ end
256
+ break
257
+ when skip(IGNORE)
258
+ ;
259
+ else
260
+ raise ParserError, "unexpected token in object at '#{peek(20)}'!"
261
+ end
262
+ end
263
+ result
264
+ end
265
+ end
266
+ end
267
+ end
@@ -0,0 +1,8 @@
1
+ module JSON
2
+ # JSON version
3
+ VERSION = '1.1.5'
4
+ VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc:
5
+ VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
6
+ VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
7
+ VERSION_BUILD = VERSION_ARRAY[2] # :nodoc:
8
+ end
@@ -0,0 +1 @@
1
+ "A JSON payload should be an object or array, not a string."
@@ -0,0 +1 @@
1
+ {"Extra value after close": true} "misplaced quoted value"
@@ -0,0 +1 @@
1
+ {"Illegal expression": 1 + 2}
@@ -0,0 +1 @@
1
+ {"Illegal invocation": alert()}
@@ -0,0 +1 @@
1
+ {"Numbers cannot have leading zeroes": 013}
@@ -0,0 +1 @@
1
+ {"Numbers cannot be hex": 0x14}
@@ -0,0 +1 @@
1
+ [[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]
@@ -0,0 +1 @@
1
+ {"Missing colon" null}
@@ -0,0 +1 @@
1
+ ["Unclosed array"
@@ -0,0 +1 @@
1
+ {"Double colon":: null}
@@ -0,0 +1 @@
1
+ {"Comma instead of colon", null}
@@ -0,0 +1 @@
1
+ ["Colon instead of comma": false]
@@ -0,0 +1 @@
1
+ ["Bad value", truth]
@@ -0,0 +1 @@
1
+ ['single quote']
@@ -0,0 +1 @@
1
+ ["tab character in string "]
@@ -0,0 +1,2 @@
1
+ ["line
2
+ break"]
@@ -0,0 +1,2 @@
1
+ ["line\
2
+ break"]
@@ -0,0 +1 @@
1
+ {unquoted_key: "keys must be quoted"}
@@ -0,0 +1 @@
1
+ ["extra comma",]
@@ -0,0 +1 @@
1
+ ["double extra comma",,]
@@ -0,0 +1 @@
1
+ [ , "<-- missing value"]
@@ -0,0 +1 @@
1
+ ["Comma after the close"],
@@ -0,0 +1 @@
1
+ ["Extra close"]]
@@ -0,0 +1 @@
1
+ {"Extra comma": true,}
@@ -0,0 +1,56 @@
1
+ [
2
+ "JSON Test Pattern pass1",
3
+ {"object with 1 member":["array with 1 element"]},
4
+ {},
5
+ [],
6
+ -42,
7
+ true,
8
+ false,
9
+ null,
10
+ {
11
+ "integer": 1234567890,
12
+ "real": -9876.543210,
13
+ "e": 0.123456789e-12,
14
+ "E": 1.234567890E+34,
15
+ "": 23456789012E666,
16
+ "zero": 0,
17
+ "one": 1,
18
+ "space": " ",
19
+ "quote": "\"",
20
+ "backslash": "\\",
21
+ "controls": "\b\f\n\r\t",
22
+ "slash": "/ & \/",
23
+ "alpha": "abcdefghijklmnopqrstuvwyz",
24
+ "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ",
25
+ "digit": "0123456789",
26
+ "special": "`1~!@#$%^&*()_+-={':[,]}|;.</>?",
27
+ "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A",
28
+ "true": true,
29
+ "false": false,
30
+ "null": null,
31
+ "array":[ ],
32
+ "object":{ },
33
+ "address": "50 St. James Street",
34
+ "url": "http://www.JSON.org/",
35
+ "comment": "// /* <!-- --",
36
+ "# -- --> */": " ",
37
+ " s p a c e d " :[1,2 , 3
38
+
39
+ ,
40
+
41
+ 4 , 5 , 6 ,7 ],
42
+ "compact": [1,2,3,4,5,6,7],
43
+ "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}",
44
+ "quotes": "&#34; \u0022 %22 0x22 034 &#x22;",
45
+ "\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?"
46
+ : "A key can be any string"
47
+ },
48
+ 0.5 ,98.6
49
+ ,
50
+ 99.44
51
+ ,
52
+
53
+ 1066
54
+
55
+
56
+ ,"rosebud"]
@@ -0,0 +1 @@
1
+ ["Illegal backslash escape: \x15"]
@@ -0,0 +1 @@
1
+ ["Illegal backslash escape: \'"]
@@ -0,0 +1 @@
1
+ ["Illegal backslash escape: \017"]
@@ -0,0 +1 @@
1
+ [[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]]
@@ -0,0 +1 @@
1
+ ["tab\ character\ in\ string\ "]
@@ -0,0 +1,6 @@
1
+ {
2
+ "JSON Test Pattern pass3": {
3
+ "The outermost value": "must be an object or array.",
4
+ "In this test": "It is an object."
5
+ }
6
+ }
@@ -0,0 +1,312 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ require 'test/unit'
5
+ case ENV['JSON']
6
+ when 'pure' then require 'json/pure'
7
+ when 'ext' then require 'json/ext'
8
+ else require 'json'
9
+ end
10
+ require 'stringio'
11
+
12
+ class TC_JSON < Test::Unit::TestCase
13
+ include JSON
14
+
15
+ def setup
16
+ @ary = [1, "foo", 3.14, 4711.0, 2.718, nil, [1,-2,3], false, true].map do
17
+ |x| [x]
18
+ end
19
+ @ary_to_parse = ["1", '"foo"', "3.14", "4711.0", "2.718", "null",
20
+ "[1,-2,3]", "false", "true"].map do
21
+ |x| "[#{x}]"
22
+ end
23
+ @hash = {
24
+ 'a' => 2,
25
+ 'b' => 3.141,
26
+ 'c' => 'c',
27
+ 'd' => [ 1, "b", 3.14 ],
28
+ 'e' => { 'foo' => 'bar' },
29
+ 'g' => "\"\0\037",
30
+ 'h' => 1000.0,
31
+ 'i' => 0.001
32
+ }
33
+ @json = '{"a":2,"b":3.141,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},'\
34
+ '"g":"\\"\\u0000\\u001f","h":1.0E3,"i":1.0E-3}'
35
+ end
36
+
37
+ def test_construction
38
+ parser = JSON::Parser.new('test')
39
+ assert_equal 'test', parser.source
40
+ end
41
+
42
+ def assert_equal_float(expected, is)
43
+ assert_in_delta(expected.first, is.first, 1e-2)
44
+ end
45
+
46
+ def test_parse_simple_arrays
47
+ assert_equal([], parse('[]'))
48
+ assert_equal([], parse(' [ ] '))
49
+ assert_equal([nil], parse('[null]'))
50
+ assert_equal([false], parse('[false]'))
51
+ assert_equal([true], parse('[true]'))
52
+ assert_equal([-23], parse('[-23]'))
53
+ assert_equal([23], parse('[23]'))
54
+ assert_equal([0.23], parse('[0.23]'))
55
+ assert_equal([0.0], parse('[0e0]'))
56
+ assert_raises(JSON::ParserError) { parse('[+23.2]') }
57
+ assert_raises(JSON::ParserError) { parse('[+23]') }
58
+ assert_raises(JSON::ParserError) { parse('[.23]') }
59
+ assert_raises(JSON::ParserError) { parse('[023]') }
60
+ assert_equal_float [3.141], parse('[3.141]')
61
+ assert_equal_float [-3.141], parse('[-3.141]')
62
+ assert_equal_float [3.141], parse('[3141e-3]')
63
+ assert_equal_float [3.141], parse('[3141.1e-3]')
64
+ assert_equal_float [3.141], parse('[3141E-3]')
65
+ assert_equal_float [3.141], parse('[3141.0E-3]')
66
+ assert_equal_float [-3.141], parse('[-3141.0e-3]')
67
+ assert_equal_float [-3.141], parse('[-3141e-3]')
68
+ assert_raises(ParserError) { parse('[NaN]') }
69
+ assert parse('[NaN]', :allow_nan => true).first.nan?
70
+ assert_raises(ParserError) { parse('[Infinity]') }
71
+ assert_equal [1.0/0], parse('[Infinity]', :allow_nan => true)
72
+ assert_raises(ParserError) { parse('[-Infinity]') }
73
+ assert_equal [-1.0/0], parse('[-Infinity]', :allow_nan => true)
74
+ assert_equal([""], parse('[""]'))
75
+ assert_equal(["foobar"], parse('["foobar"]'))
76
+ assert_equal([{}], parse('[{}]'))
77
+ end
78
+
79
+ def test_parse_simple_objects
80
+ assert_equal({}, parse('{}'))
81
+ assert_equal({}, parse(' { } '))
82
+ assert_equal({ "a" => nil }, parse('{ "a" : null}'))
83
+ assert_equal({ "a" => nil }, parse('{"a":null}'))
84
+ assert_equal({ "a" => false }, parse('{ "a" : false } '))
85
+ assert_equal({ "a" => false }, parse('{"a":false}'))
86
+ assert_raises(JSON::ParserError) { parse('{false}') }
87
+ assert_equal({ "a" => true }, parse('{"a":true}'))
88
+ assert_equal({ "a" => true }, parse(' { "a" : true } '))
89
+ assert_equal({ "a" => -23 }, parse(' { "a" : -23 } '))
90
+ assert_equal({ "a" => -23 }, parse(' { "a" : -23 } '))
91
+ assert_equal({ "a" => 23 }, parse('{"a":23 } '))
92
+ assert_equal({ "a" => 23 }, parse(' { "a" : 23 } '))
93
+ assert_equal({ "a" => 0.23 }, parse(' { "a" : 0.23 } '))
94
+ assert_equal({ "a" => 0.23 }, parse(' { "a" : 0.23 } '))
95
+ end
96
+
97
+ begin
98
+ require 'permutation'
99
+ def test_parse_more_complex_arrays
100
+ a = [ nil, false, true, "foßbar", [ "n€st€d", true ], { "nested" => true, "n€ßt€ð2" => {} }]
101
+ perms = Permutation.for a
102
+ perms.each do |perm|
103
+ orig_ary = perm.project
104
+ json = pretty_generate(orig_ary)
105
+ assert_equal orig_ary, parse(json)
106
+ end
107
+ end
108
+
109
+ def test_parse_complex_objects
110
+ a = [ nil, false, true, "foßbar", [ "n€st€d", true ], { "nested" => true, "n€ßt€ð2" => {} }]
111
+ perms = Permutation.for a
112
+ perms.each do |perm|
113
+ s = "a"
114
+ orig_obj = perm.project.inject({}) { |h, x| h[s.dup] = x; s = s.succ; h }
115
+ json = pretty_generate(orig_obj)
116
+ assert_equal orig_obj, parse(json)
117
+ end
118
+ end
119
+ rescue LoadError
120
+ warn "Skipping permutation tests."
121
+ end
122
+
123
+ def test_parse_arrays
124
+ assert_equal([1,2,3], parse('[1,2,3]'))
125
+ assert_equal([1.2,2,3], parse('[1.2,2,3]'))
126
+ assert_equal([[],[[],[]]], parse('[[],[[],[]]]'))
127
+ end
128
+
129
+ def test_parse_values
130
+ assert_equal([""], parse('[""]'))
131
+ assert_equal(["\\"], parse('["\\\\"]'))
132
+ assert_equal(['"'], parse('["\""]'))
133
+ assert_equal(['\\"\\'], parse('["\\\\\\"\\\\"]'))
134
+ assert_equal(["\"\b\n\r\t\0\037"],
135
+ parse('["\"\b\n\r\t\u0000\u001f"]'))
136
+ for i in 0 ... @ary.size
137
+ assert_equal(@ary[i], parse(@ary_to_parse[i]))
138
+ end
139
+ end
140
+
141
+ def test_parse_array
142
+ assert_equal([], parse('[]'))
143
+ assert_equal([], parse(' [ ] '))
144
+ assert_equal([1], parse('[1]'))
145
+ assert_equal([1], parse(' [ 1 ] '))
146
+ assert_equal(@ary,
147
+ parse('[[1],["foo"],[3.14],[47.11e+2],[2718.0E-3],[null],[[1,-2,3]]'\
148
+ ',[false],[true]]'))
149
+ assert_equal(@ary, parse(%Q{ [ [1] , ["foo"] , [3.14] \t , [47.11e+2]
150
+ , [2718.0E-3 ],\r[ null] , [[1, -2, 3 ]], [false ],[ true]\n ] }))
151
+ end
152
+
153
+ class SubArray < Array; end
154
+
155
+ def test_parse_array_custom_class
156
+ res = parse('[]', :array_class => SubArray)
157
+ assert_equal([], res)
158
+ assert_equal(SubArray, res.class)
159
+ end
160
+
161
+ def test_parse_object
162
+ assert_equal({}, parse('{}'))
163
+ assert_equal({}, parse(' { } '))
164
+ assert_equal({'foo'=>'bar'}, parse('{"foo":"bar"}'))
165
+ assert_equal({'foo'=>'bar'}, parse(' { "foo" : "bar" } '))
166
+ end
167
+
168
+ class SubHash < Hash; end
169
+
170
+ def test_parse_object_custom_class
171
+ res = parse('{}', :object_class => SubHash)
172
+ assert_equal({}, res)
173
+ assert_equal(SubHash, res.class)
174
+ end
175
+
176
+ def test_parser_reset
177
+ parser = Parser.new(@json)
178
+ assert_equal(@hash, parser.parse)
179
+ assert_equal(@hash, parser.parse)
180
+ end
181
+
182
+ def test_comments
183
+ json = <<EOT
184
+ {
185
+ "key1":"value1", // eol comment
186
+ "key2":"value2" /* multi line
187
+ * comment */,
188
+ "key3":"value3" /* multi line
189
+ // nested eol comment
190
+ * comment */
191
+ }
192
+ EOT
193
+ assert_equal(
194
+ { "key1" => "value1", "key2" => "value2", "key3" => "value3" },
195
+ parse(json))
196
+ json = <<EOT
197
+ {
198
+ "key1":"value1" /* multi line
199
+ // nested eol comment
200
+ /* illegal nested multi line comment */
201
+ * comment */
202
+ }
203
+ EOT
204
+ assert_raises(ParserError) { parse(json) }
205
+ json = <<EOT
206
+ {
207
+ "key1":"value1" /* multi line
208
+ // nested eol comment
209
+ closed multi comment */
210
+ and again, throw an Error */
211
+ }
212
+ EOT
213
+ assert_raises(ParserError) { parse(json) }
214
+ json = <<EOT
215
+ {
216
+ "key1":"value1" /*/*/
217
+ }
218
+ EOT
219
+ assert_equal({ "key1" => "value1" }, parse(json))
220
+ end
221
+
222
+ def test_backslash
223
+ data = [ '\\.(?i:gif|jpe?g|png)$' ]
224
+ json = '["\\\\.(?i:gif|jpe?g|png)$"]'
225
+ assert_equal json, JSON.unparse(data)
226
+ assert_equal data, JSON.parse(json)
227
+ #
228
+ data = [ '\\"' ]
229
+ json = '["\\\\\""]'
230
+ assert_equal json, JSON.unparse(data)
231
+ assert_equal data, JSON.parse(json)
232
+ #
233
+ json = '["\/"]'
234
+ data = JSON.parse(json)
235
+ assert_equal ['/'], data
236
+ assert_equal json, JSON.unparse(data)
237
+ #
238
+ json = '["\""]'
239
+ data = JSON.parse(json)
240
+ assert_equal ['"'], data
241
+ assert_equal json, JSON.unparse(data)
242
+ json = '["\\\'"]'
243
+ data = JSON.parse(json)
244
+ assert_equal ["'"], data
245
+ assert_equal '["\'"]', JSON.unparse(data)
246
+ end
247
+
248
+ def test_wrong_inputs
249
+ assert_raises(ParserError) { JSON.parse('"foo"') }
250
+ assert_raises(ParserError) { JSON.parse('123') }
251
+ assert_raises(ParserError) { JSON.parse('[] bla') }
252
+ assert_raises(ParserError) { JSON.parse('[] 1') }
253
+ assert_raises(ParserError) { JSON.parse('[] []') }
254
+ assert_raises(ParserError) { JSON.parse('[] {}') }
255
+ assert_raises(ParserError) { JSON.parse('{} []') }
256
+ assert_raises(ParserError) { JSON.parse('{} {}') }
257
+ assert_raises(ParserError) { JSON.parse('[NULL]') }
258
+ assert_raises(ParserError) { JSON.parse('[FALSE]') }
259
+ assert_raises(ParserError) { JSON.parse('[TRUE]') }
260
+ assert_raises(ParserError) { JSON.parse('[07] ') }
261
+ assert_raises(ParserError) { JSON.parse('[0a]') }
262
+ assert_raises(ParserError) { JSON.parse('[1.]') }
263
+ assert_raises(ParserError) { JSON.parse(' ') }
264
+ end
265
+
266
+ def test_nesting
267
+ assert_raises(JSON::NestingError) { JSON.parse '[[]]', :max_nesting => 1 }
268
+ assert_raises(JSON::NestingError) { JSON.parser.new('[[]]', :max_nesting => 1).parse }
269
+ assert_equal [[]], JSON.parse('[[]]', :max_nesting => 2)
270
+ too_deep = '[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]'
271
+ too_deep_ary = eval too_deep
272
+ assert_raises(JSON::NestingError) { JSON.parse too_deep }
273
+ assert_raises(JSON::NestingError) { JSON.parser.new(too_deep).parse }
274
+ assert_raises(JSON::NestingError) { JSON.parse too_deep, :max_nesting => 19 }
275
+ ok = JSON.parse too_deep, :max_nesting => 20
276
+ assert_equal too_deep_ary, ok
277
+ ok = JSON.parse too_deep, :max_nesting => nil
278
+ assert_equal too_deep_ary, ok
279
+ ok = JSON.parse too_deep, :max_nesting => false
280
+ assert_equal too_deep_ary, ok
281
+ ok = JSON.parse too_deep, :max_nesting => 0
282
+ assert_equal too_deep_ary, ok
283
+ assert_raises(JSON::NestingError) { JSON.generate [[]], :max_nesting => 1 }
284
+ assert_equal '[[]]', JSON.generate([[]], :max_nesting => 2)
285
+ assert_raises(JSON::NestingError) { JSON.generate too_deep_ary }
286
+ assert_raises(JSON::NestingError) { JSON.generate too_deep_ary, :max_nesting => 19 }
287
+ ok = JSON.generate too_deep_ary, :max_nesting => 20
288
+ assert_equal too_deep, ok
289
+ ok = JSON.generate too_deep_ary, :max_nesting => nil
290
+ assert_equal too_deep, ok
291
+ ok = JSON.generate too_deep_ary, :max_nesting => false
292
+ assert_equal too_deep, ok
293
+ ok = JSON.generate too_deep_ary, :max_nesting => 0
294
+ assert_equal too_deep, ok
295
+ end
296
+
297
+ def test_load_dump
298
+ too_deep = '[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]'
299
+ assert_equal too_deep, JSON.dump(eval(too_deep))
300
+ assert_kind_of String, Marshal.dump(eval(too_deep))
301
+ assert_raises(ArgumentError) { JSON.dump(eval(too_deep), 19) }
302
+ assert_raises(ArgumentError) { Marshal.dump(eval(too_deep), 19) }
303
+ assert_equal too_deep, JSON.dump(eval(too_deep), 20)
304
+ assert_kind_of String, Marshal.dump(eval(too_deep), 20)
305
+ output = StringIO.new
306
+ JSON.dump(eval(too_deep), output)
307
+ assert_equal too_deep, output.string
308
+ output = StringIO.new
309
+ JSON.dump(eval(too_deep), output, 20)
310
+ assert_equal too_deep, output.string
311
+ end
312
+ end