json 1.4.3-java

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 (60) hide show
  1. data/lib/json.rb +10 -0
  2. data/lib/json/Array.xpm +21 -0
  3. data/lib/json/FalseClass.xpm +21 -0
  4. data/lib/json/Hash.xpm +21 -0
  5. data/lib/json/Key.xpm +73 -0
  6. data/lib/json/NilClass.xpm +21 -0
  7. data/lib/json/Numeric.xpm +28 -0
  8. data/lib/json/String.xpm +96 -0
  9. data/lib/json/TrueClass.xpm +21 -0
  10. data/lib/json/add/core.rb +148 -0
  11. data/lib/json/add/rails.rb +58 -0
  12. data/lib/json/common.rb +397 -0
  13. data/lib/json/editor.rb +1371 -0
  14. data/lib/json/ext.rb +15 -0
  15. data/lib/json/ext/generator.jar +0 -0
  16. data/lib/json/ext/parser.jar +0 -0
  17. data/lib/json/json.xpm +1499 -0
  18. data/lib/json/pure.rb +77 -0
  19. data/lib/json/pure/generator.rb +452 -0
  20. data/lib/json/pure/parser.rb +307 -0
  21. data/lib/json/version.rb +8 -0
  22. data/tests/fixtures/fail1.json +1 -0
  23. data/tests/fixtures/fail10.json +1 -0
  24. data/tests/fixtures/fail11.json +1 -0
  25. data/tests/fixtures/fail12.json +1 -0
  26. data/tests/fixtures/fail13.json +1 -0
  27. data/tests/fixtures/fail14.json +1 -0
  28. data/tests/fixtures/fail18.json +1 -0
  29. data/tests/fixtures/fail19.json +1 -0
  30. data/tests/fixtures/fail2.json +1 -0
  31. data/tests/fixtures/fail20.json +1 -0
  32. data/tests/fixtures/fail21.json +1 -0
  33. data/tests/fixtures/fail22.json +1 -0
  34. data/tests/fixtures/fail23.json +1 -0
  35. data/tests/fixtures/fail24.json +1 -0
  36. data/tests/fixtures/fail25.json +1 -0
  37. data/tests/fixtures/fail27.json +2 -0
  38. data/tests/fixtures/fail28.json +2 -0
  39. data/tests/fixtures/fail3.json +1 -0
  40. data/tests/fixtures/fail4.json +1 -0
  41. data/tests/fixtures/fail5.json +1 -0
  42. data/tests/fixtures/fail6.json +1 -0
  43. data/tests/fixtures/fail7.json +1 -0
  44. data/tests/fixtures/fail8.json +1 -0
  45. data/tests/fixtures/fail9.json +1 -0
  46. data/tests/fixtures/pass1.json +56 -0
  47. data/tests/fixtures/pass15.json +1 -0
  48. data/tests/fixtures/pass16.json +1 -0
  49. data/tests/fixtures/pass17.json +1 -0
  50. data/tests/fixtures/pass2.json +1 -0
  51. data/tests/fixtures/pass26.json +1 -0
  52. data/tests/fixtures/pass3.json +6 -0
  53. data/tests/test_json.rb +361 -0
  54. data/tests/test_json_addition.rb +162 -0
  55. data/tests/test_json_encoding.rb +68 -0
  56. data/tests/test_json_fixtures.rb +34 -0
  57. data/tests/test_json_generate.rb +122 -0
  58. data/tests/test_json_rails.rb +144 -0
  59. data/tests/test_json_unicode.rb +76 -0
  60. metadata +122 -0
@@ -0,0 +1,307 @@
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
+ # escaped special characters:
10
+ \\["\\\/bfnrt] |
11
+ \\u[0-9a-fA-F]{4} |
12
+ # match all but escaped special characters:
13
+ \\[\x20-\x21\x23-\x2e\x30-\x5b\x5d-\x61\x63-\x65\x67-\x6d\x6f-\x71\x73\x75-\xff])*)
14
+ "/nx
15
+ INTEGER = /(-?0|-?[1-9]\d*)/
16
+ FLOAT = /(-?
17
+ (?:0|[1-9]\d*)
18
+ (?:
19
+ \.\d+(?i:e[+-]?\d+) |
20
+ \.\d+ |
21
+ (?i:e[+-]?\d+)
22
+ )
23
+ )/x
24
+ NAN = /NaN/
25
+ INFINITY = /Infinity/
26
+ MINUS_INFINITY = /-Infinity/
27
+ OBJECT_OPEN = /\{/
28
+ OBJECT_CLOSE = /\}/
29
+ ARRAY_OPEN = /\[/
30
+ ARRAY_CLOSE = /\]/
31
+ PAIR_DELIMITER = /:/
32
+ COLLECTION_DELIMITER = /,/
33
+ TRUE = /true/
34
+ FALSE = /false/
35
+ NULL = /null/
36
+ IGNORE = %r(
37
+ (?:
38
+ //[^\n\r]*[\n\r]| # line comments
39
+ /\* # c-style comments
40
+ (?:
41
+ [^*/]| # normal chars
42
+ /[^*]| # slashes that do not start a nested comment
43
+ \*[^/]| # asterisks that do not end this comment
44
+ /(?=\*/) # single slash before this comment's end
45
+ )*
46
+ \*/ # the End of this comment
47
+ |[ \t\r\n]+ # whitespaces: space, horicontal tab, lf, cr
48
+ )+
49
+ )mx
50
+
51
+ UNPARSED = Object.new
52
+
53
+ # Creates a new JSON::Pure::Parser instance for the string _source_.
54
+ #
55
+ # It will be configured by the _opts_ hash. _opts_ can have the following
56
+ # keys:
57
+ # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
58
+ # structures. Disable depth checking with :max_nesting => false|nil|0,
59
+ # it defaults to 19.
60
+ # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
61
+ # defiance of RFC 4627 to be parsed by the Parser. This option defaults
62
+ # to false.
63
+ # * *symbolize_names*: If set to true, returns symbols for the names
64
+ # (keys) in a JSON object. Otherwise strings are returned, which is also
65
+ # the default.
66
+ # * *create_additions*: If set to false, the Parser doesn't create
67
+ # additions even if a matchin class and create_id was found. This option
68
+ # defaults to true.
69
+ # * *object_class*: Defaults to Hash
70
+ # * *array_class*: Defaults to Array
71
+ def initialize(source, opts = {})
72
+ if defined?(::Encoding)
73
+ if source.encoding == Encoding::ASCII_8BIT
74
+ b = source[0, 4].bytes.to_a
75
+ source = case
76
+ when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
77
+ source.dup.force_encoding(Encoding::UTF_32BE).encode!(Encoding::UTF_8)
78
+ when b.size >= 4 && b[0] == 0 && b[2] == 0
79
+ source.dup.force_encoding(Encoding::UTF_16BE).encode!(Encoding::UTF_8)
80
+ when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
81
+ source.dup.force_encoding(Encoding::UTF_32LE).encode!(Encoding::UTF_8)
82
+ when b.size >= 4 && b[1] == 0 && b[3] == 0
83
+ source.dup.force_encoding(Encoding::UTF_16LE).encode!(Encoding::UTF_8)
84
+ else
85
+ source.dup
86
+ end
87
+ else
88
+ source = source.encode(Encoding::UTF_8)
89
+ end
90
+ source.force_encoding(Encoding::ASCII_8BIT)
91
+ else
92
+ b = source
93
+ source = case
94
+ when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
95
+ JSON.iconv('utf-8', 'utf-32be', b)
96
+ when b.size >= 4 && b[0] == 0 && b[2] == 0
97
+ JSON.iconv('utf-8', 'utf-16be', b)
98
+ when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
99
+ JSON.iconv('utf-8', 'utf-32le', b)
100
+ when b.size >= 4 && b[1] == 0 && b[3] == 0
101
+ JSON.iconv('utf-8', 'utf-16le', b)
102
+ else
103
+ b
104
+ end
105
+ end
106
+ super source
107
+ if !opts.key?(:max_nesting) # defaults to 19
108
+ @max_nesting = 19
109
+ elsif opts[:max_nesting]
110
+ @max_nesting = opts[:max_nesting]
111
+ else
112
+ @max_nesting = 0
113
+ end
114
+ @allow_nan = !!opts[:allow_nan]
115
+ @symbolize_names = !!opts[:symbolize_names]
116
+ ca = true
117
+ ca = opts[:create_additions] if opts.key?(:create_additions)
118
+ @create_id = ca ? JSON.create_id : nil
119
+ @object_class = opts[:object_class] || Hash
120
+ @array_class = opts[:array_class] || Array
121
+ end
122
+
123
+ alias source string
124
+
125
+ # Parses the current JSON string _source_ and returns the complete data
126
+ # structure as a result.
127
+ def parse
128
+ reset
129
+ obj = nil
130
+ until eos?
131
+ case
132
+ when scan(OBJECT_OPEN)
133
+ obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
134
+ @current_nesting = 1
135
+ obj = parse_object
136
+ when scan(ARRAY_OPEN)
137
+ obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
138
+ @current_nesting = 1
139
+ obj = parse_array
140
+ when skip(IGNORE)
141
+ ;
142
+ else
143
+ raise ParserError, "source '#{peek(20)}' not in JSON!"
144
+ end
145
+ end
146
+ obj or raise ParserError, "source did not contain any JSON!"
147
+ obj
148
+ end
149
+
150
+ private
151
+
152
+ # Unescape characters in strings.
153
+ UNESCAPE_MAP = Hash.new { |h, k| h[k] = k.chr }
154
+ UNESCAPE_MAP.update({
155
+ ?" => '"',
156
+ ?\\ => '\\',
157
+ ?/ => '/',
158
+ ?b => "\b",
159
+ ?f => "\f",
160
+ ?n => "\n",
161
+ ?r => "\r",
162
+ ?t => "\t",
163
+ ?u => nil,
164
+ })
165
+
166
+ def parse_string
167
+ if scan(STRING)
168
+ return '' if self[1].empty?
169
+ string = self[1].gsub(%r((?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))+|\\[\x20-\xff]))n) do |c|
170
+ if u = UNESCAPE_MAP[$&[1]]
171
+ u
172
+ else # \uXXXX
173
+ bytes = ''
174
+ i = 0
175
+ while c[6 * i] == ?\\ && c[6 * i + 1] == ?u
176
+ bytes << c[6 * i + 2, 2].to_i(16) << c[6 * i + 4, 2].to_i(16)
177
+ i += 1
178
+ end
179
+ JSON::UTF16toUTF8.iconv(bytes)
180
+ end
181
+ end
182
+ if string.respond_to?(:force_encoding)
183
+ string.force_encoding(Encoding::UTF_8)
184
+ end
185
+ string
186
+ else
187
+ UNPARSED
188
+ end
189
+ rescue Iconv::Failure => e
190
+ raise GeneratorError, "Caught #{e.class}: #{e}"
191
+ end
192
+
193
+ def parse_value
194
+ case
195
+ when scan(FLOAT)
196
+ Float(self[1])
197
+ when scan(INTEGER)
198
+ Integer(self[1])
199
+ when scan(TRUE)
200
+ true
201
+ when scan(FALSE)
202
+ false
203
+ when scan(NULL)
204
+ nil
205
+ when (string = parse_string) != UNPARSED
206
+ string
207
+ when scan(ARRAY_OPEN)
208
+ @current_nesting += 1
209
+ ary = parse_array
210
+ @current_nesting -= 1
211
+ ary
212
+ when scan(OBJECT_OPEN)
213
+ @current_nesting += 1
214
+ obj = parse_object
215
+ @current_nesting -= 1
216
+ obj
217
+ when @allow_nan && scan(NAN)
218
+ NaN
219
+ when @allow_nan && scan(INFINITY)
220
+ Infinity
221
+ when @allow_nan && scan(MINUS_INFINITY)
222
+ MinusInfinity
223
+ else
224
+ UNPARSED
225
+ end
226
+ end
227
+
228
+ def parse_array
229
+ raise NestingError, "nesting of #@current_nesting is too deep" if
230
+ @max_nesting.nonzero? && @current_nesting > @max_nesting
231
+ result = @array_class.new
232
+ delim = false
233
+ until eos?
234
+ case
235
+ when (value = parse_value) != UNPARSED
236
+ delim = false
237
+ result << value
238
+ skip(IGNORE)
239
+ if scan(COLLECTION_DELIMITER)
240
+ delim = true
241
+ elsif match?(ARRAY_CLOSE)
242
+ ;
243
+ else
244
+ raise ParserError, "expected ',' or ']' in array at '#{peek(20)}'!"
245
+ end
246
+ when scan(ARRAY_CLOSE)
247
+ if delim
248
+ raise ParserError, "expected next element in array at '#{peek(20)}'!"
249
+ end
250
+ break
251
+ when skip(IGNORE)
252
+ ;
253
+ else
254
+ raise ParserError, "unexpected token in array at '#{peek(20)}'!"
255
+ end
256
+ end
257
+ result
258
+ end
259
+
260
+ def parse_object
261
+ raise NestingError, "nesting of #@current_nesting is too deep" if
262
+ @max_nesting.nonzero? && @current_nesting > @max_nesting
263
+ result = @object_class.new
264
+ delim = false
265
+ until eos?
266
+ case
267
+ when (string = parse_string) != UNPARSED
268
+ skip(IGNORE)
269
+ unless scan(PAIR_DELIMITER)
270
+ raise ParserError, "expected ':' in object at '#{peek(20)}'!"
271
+ end
272
+ skip(IGNORE)
273
+ unless (value = parse_value).equal? UNPARSED
274
+ result[@symbolize_names ? string.to_sym : string] = value
275
+ delim = false
276
+ skip(IGNORE)
277
+ if scan(COLLECTION_DELIMITER)
278
+ delim = true
279
+ elsif match?(OBJECT_CLOSE)
280
+ ;
281
+ else
282
+ raise ParserError, "expected ',' or '}' in object at '#{peek(20)}'!"
283
+ end
284
+ else
285
+ raise ParserError, "expected value in object at '#{peek(20)}'!"
286
+ end
287
+ when scan(OBJECT_CLOSE)
288
+ if delim
289
+ raise ParserError, "expected next name, value pair in object at '#{peek(20)}'!"
290
+ end
291
+ if @create_id and klassname = result[@create_id]
292
+ klass = JSON.deep_const_get klassname
293
+ break unless klass and klass.json_creatable?
294
+ result = klass.json_create(result)
295
+ end
296
+ break
297
+ when skip(IGNORE)
298
+ ;
299
+ else
300
+ raise ParserError, "unexpected token in object at '#{peek(20)}'!"
301
+ end
302
+ end
303
+ result
304
+ end
305
+ end
306
+ end
307
+ end
@@ -0,0 +1,8 @@
1
+ module JSON
2
+ # JSON version
3
+ VERSION = '1.4.3'
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"]