json-jruby 1.1.2-universal-java-1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/lib/json.rb +235 -0
  2. data/lib/json/add/core.rb +127 -0
  3. data/lib/json/add/rails.rb +58 -0
  4. data/lib/json/common.rb +354 -0
  5. data/lib/json/ext.rb +13 -0
  6. data/lib/json/ext/generator.jar +0 -0
  7. data/lib/json/ext/parser.jar +0 -0
  8. data/lib/json/pure.rb +75 -0
  9. data/lib/json/pure/generator.rb +394 -0
  10. data/lib/json/pure/parser.rb +259 -0
  11. data/lib/json/version.rb +9 -0
  12. data/tests/fixtures/fail1.json +1 -0
  13. data/tests/fixtures/fail10.json +1 -0
  14. data/tests/fixtures/fail11.json +1 -0
  15. data/tests/fixtures/fail12.json +1 -0
  16. data/tests/fixtures/fail13.json +1 -0
  17. data/tests/fixtures/fail14.json +1 -0
  18. data/tests/fixtures/fail18.json +1 -0
  19. data/tests/fixtures/fail19.json +1 -0
  20. data/tests/fixtures/fail2.json +1 -0
  21. data/tests/fixtures/fail20.json +1 -0
  22. data/tests/fixtures/fail21.json +1 -0
  23. data/tests/fixtures/fail22.json +1 -0
  24. data/tests/fixtures/fail23.json +1 -0
  25. data/tests/fixtures/fail24.json +1 -0
  26. data/tests/fixtures/fail25.json +1 -0
  27. data/tests/fixtures/fail27.json +2 -0
  28. data/tests/fixtures/fail28.json +2 -0
  29. data/tests/fixtures/fail3.json +1 -0
  30. data/tests/fixtures/fail4.json +1 -0
  31. data/tests/fixtures/fail5.json +1 -0
  32. data/tests/fixtures/fail6.json +1 -0
  33. data/tests/fixtures/fail7.json +1 -0
  34. data/tests/fixtures/fail8.json +1 -0
  35. data/tests/fixtures/fail9.json +1 -0
  36. data/tests/fixtures/pass1.json +56 -0
  37. data/tests/fixtures/pass15.json +1 -0
  38. data/tests/fixtures/pass16.json +1 -0
  39. data/tests/fixtures/pass17.json +1 -0
  40. data/tests/fixtures/pass2.json +1 -0
  41. data/tests/fixtures/pass26.json +1 -0
  42. data/tests/fixtures/pass3.json +6 -0
  43. data/tests/runner.rb +26 -0
  44. data/tests/test_json.rb +294 -0
  45. data/tests/test_json_addition.rb +144 -0
  46. data/tests/test_json_fixtures.rb +30 -0
  47. data/tests/test_json_generate.rb +100 -0
  48. data/tests/test_json_rails.rb +114 -0
  49. data/tests/test_json_unicode.rb +61 -0
  50. metadata +99 -0
@@ -0,0 +1,259 @@
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
+ def initialize(source, opts = {})
65
+ super
66
+ if !opts.key?(:max_nesting) # defaults to 19
67
+ @max_nesting = 19
68
+ elsif opts[:max_nesting]
69
+ @max_nesting = opts[:max_nesting]
70
+ else
71
+ @max_nesting = 0
72
+ end
73
+ @allow_nan = !!opts[:allow_nan]
74
+ ca = true
75
+ ca = opts[:create_additions] if opts.key?(:create_additions)
76
+ @create_id = ca ? JSON.create_id : nil
77
+ end
78
+
79
+ alias source string
80
+
81
+ # Parses the current JSON string _source_ and returns the complete data
82
+ # structure as a result.
83
+ def parse
84
+ reset
85
+ obj = nil
86
+ until eos?
87
+ case
88
+ when scan(OBJECT_OPEN)
89
+ obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
90
+ @current_nesting = 1
91
+ obj = parse_object
92
+ when scan(ARRAY_OPEN)
93
+ obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
94
+ @current_nesting = 1
95
+ obj = parse_array
96
+ when skip(IGNORE)
97
+ ;
98
+ else
99
+ raise ParserError, "source '#{peek(20)}' not in JSON!"
100
+ end
101
+ end
102
+ obj or raise ParserError, "source did not contain any JSON!"
103
+ obj
104
+ end
105
+
106
+ private
107
+
108
+ # Unescape characters in strings.
109
+ UNESCAPE_MAP = Hash.new { |h, k| h[k] = k.chr }
110
+ UNESCAPE_MAP.update({
111
+ ?" => '"',
112
+ ?\\ => '\\',
113
+ ?/ => '/',
114
+ ?b => "\b",
115
+ ?f => "\f",
116
+ ?n => "\n",
117
+ ?r => "\r",
118
+ ?t => "\t",
119
+ ?u => nil,
120
+ })
121
+
122
+ def parse_string
123
+ if scan(STRING)
124
+ return '' if self[1].empty?
125
+ self[1].gsub(%r((?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))+|\\[\x20-\xff]))n) do |c|
126
+ if u = UNESCAPE_MAP[c[1]]
127
+ u
128
+ else # \uXXXX
129
+ bytes = ''
130
+ i = 0
131
+ while c[6 * i] == ?\\ && c[6 * i + 1] == ?u
132
+ bytes << c[6 * i + 2, 2].to_i(16) << c[6 * i + 4, 2].to_i(16)
133
+ i += 1
134
+ end
135
+ JSON::UTF16toUTF8.iconv(bytes)
136
+ end
137
+ end
138
+ else
139
+ UNPARSED
140
+ end
141
+ rescue Iconv::Failure => e
142
+ raise GeneratorError, "Caught #{e.class}: #{e}"
143
+ end
144
+
145
+ def parse_value
146
+ case
147
+ when scan(FLOAT)
148
+ Float(self[1])
149
+ when scan(INTEGER)
150
+ Integer(self[1])
151
+ when scan(TRUE)
152
+ true
153
+ when scan(FALSE)
154
+ false
155
+ when scan(NULL)
156
+ nil
157
+ when (string = parse_string) != UNPARSED
158
+ string
159
+ when scan(ARRAY_OPEN)
160
+ @current_nesting += 1
161
+ ary = parse_array
162
+ @current_nesting -= 1
163
+ ary
164
+ when scan(OBJECT_OPEN)
165
+ @current_nesting += 1
166
+ obj = parse_object
167
+ @current_nesting -= 1
168
+ obj
169
+ when @allow_nan && scan(NAN)
170
+ NaN
171
+ when @allow_nan && scan(INFINITY)
172
+ Infinity
173
+ when @allow_nan && scan(MINUS_INFINITY)
174
+ MinusInfinity
175
+ else
176
+ UNPARSED
177
+ end
178
+ end
179
+
180
+ def parse_array
181
+ raise NestingError, "nesting of #@current_nesting is to deep" if
182
+ @max_nesting.nonzero? && @current_nesting > @max_nesting
183
+ result = []
184
+ delim = false
185
+ until eos?
186
+ case
187
+ when (value = parse_value) != UNPARSED
188
+ delim = false
189
+ result << value
190
+ skip(IGNORE)
191
+ if scan(COLLECTION_DELIMITER)
192
+ delim = true
193
+ elsif match?(ARRAY_CLOSE)
194
+ ;
195
+ else
196
+ raise ParserError, "expected ',' or ']' in array at '#{peek(20)}'!"
197
+ end
198
+ when scan(ARRAY_CLOSE)
199
+ if delim
200
+ raise ParserError, "expected next element in array at '#{peek(20)}'!"
201
+ end
202
+ break
203
+ when skip(IGNORE)
204
+ ;
205
+ else
206
+ raise ParserError, "unexpected token in array at '#{peek(20)}'!"
207
+ end
208
+ end
209
+ result
210
+ end
211
+
212
+ def parse_object
213
+ raise NestingError, "nesting of #@current_nesting is to deep" if
214
+ @max_nesting.nonzero? && @current_nesting > @max_nesting
215
+ result = {}
216
+ delim = false
217
+ until eos?
218
+ case
219
+ when (string = parse_string) != UNPARSED
220
+ skip(IGNORE)
221
+ unless scan(PAIR_DELIMITER)
222
+ raise ParserError, "expected ':' in object at '#{peek(20)}'!"
223
+ end
224
+ skip(IGNORE)
225
+ unless (value = parse_value).equal? UNPARSED
226
+ result[string] = value
227
+ delim = false
228
+ skip(IGNORE)
229
+ if scan(COLLECTION_DELIMITER)
230
+ delim = true
231
+ elsif match?(OBJECT_CLOSE)
232
+ ;
233
+ else
234
+ raise ParserError, "expected ',' or '}' in object at '#{peek(20)}'!"
235
+ end
236
+ else
237
+ raise ParserError, "expected value in object at '#{peek(20)}'!"
238
+ end
239
+ when scan(OBJECT_CLOSE)
240
+ if delim
241
+ raise ParserError, "expected next name, value pair in object at '#{peek(20)}'!"
242
+ end
243
+ if @create_id and klassname = result[@create_id]
244
+ klass = JSON.deep_const_get klassname
245
+ break unless klass and klass.json_creatable?
246
+ result = klass.json_create(result)
247
+ end
248
+ break
249
+ when skip(IGNORE)
250
+ ;
251
+ else
252
+ raise ParserError, "unexpected token in object at '#{peek(20)}'!"
253
+ end
254
+ end
255
+ result
256
+ end
257
+ end
258
+ end
259
+ end
@@ -0,0 +1,9 @@
1
+ module JSON
2
+ # JSON version
3
+ VERSION = '1.1.2'
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
+ VARIANT_BINARY = false
9
+ 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
+ }
data/tests/runner.rb ADDED
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test/unit/ui/console/testrunner'
4
+ require 'test/unit/testsuite'
5
+ $:.unshift File.expand_path(File.dirname($0))
6
+ $:.unshift 'tests'
7
+ require 'test_json'
8
+ require 'test_json_generate'
9
+ require 'test_json_unicode'
10
+ require 'test_json_addition'
11
+ require 'test_json_rails'
12
+ require 'test_json_fixtures'
13
+
14
+ class TS_AllTests
15
+ def self.suite
16
+ suite = Test::Unit::TestSuite.new name
17
+ suite << TC_JSONGenerate.suite
18
+ suite << TC_JSON.suite
19
+ suite << TC_JSONUnicode.suite
20
+ suite << TC_JSONAddition.suite
21
+ suite << TC_JSONRails.suite
22
+ suite << TC_JSONFixtures.suite
23
+ end
24
+ end
25
+ Test::Unit::UI::Console::TestRunner.run(TS_AllTests)
26
+ # vim: set et sw=2 ts=2: