json 0.4.2 → 0.4.3

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.

data/CHANGES CHANGED
@@ -1,3 +1,15 @@
1
+ 2007-02-09 (0.4.3)
2
+ * Conform more to RFC4627 for JSON: This means JSON strings
3
+ now always must contain exactly one object "{ ... }" or array "[ ... ]" in
4
+ order to be parsed without raising an exception. The definition of what
5
+ constitutes a whitespace is narrower in JSON than in Ruby ([ \t\r\n]), and
6
+ there are differences in floats and integers (no octals or hexadecimals) as
7
+ well.
8
+ * Added aliases generate and pretty_generate of unparse and pretty_unparse.
9
+ * Fixed a test case.
10
+ * Catch an Іconv::InvalidEncoding exception, that seems to occur on some Sun
11
+ boxes with SunOS 5.8, if iconv doesn't support utf16 conversions. This was
12
+ reported by Andrew R Jackson <andrewj@bcm.tmc.edu>, thanks a bunch!
1
13
  2006-08-25 (0.4.2)
2
14
  * Fixed a bug in handling solidi (/-characters), that was reported by
3
15
  Kevin Gilpin <kevin.gilpin@alum.mit.edu>.
data/README CHANGED
@@ -5,6 +5,10 @@ Just type into the command line as root:
5
5
 
6
6
  # ruby install.rb
7
7
 
8
+ or
9
+
10
+ # rake install
11
+
8
12
  Testing and Examples
9
13
  ====================
10
14
 
@@ -12,6 +16,10 @@ To run the tests type:
12
16
 
13
17
  $ ruby -I lib tests/runner.rb
14
18
 
19
+ or
20
+
21
+ $ rake test
22
+
15
23
  To get an idea how this library is used also look at the tests (until I have
16
24
  time to better document it.)
17
25
 
@@ -23,5 +31,5 @@ Florian Frank <flori@ping.de>
23
31
  License
24
32
  =======
25
33
 
26
- GNU General Public License (GPL)
34
+ GNU General Public License (GPL), Version 2
27
35
 
data/Rakefile CHANGED
@@ -5,19 +5,11 @@ include Config
5
5
 
6
6
  PKG_NAME = 'json'
7
7
  PKG_VERSION = File.read('VERSION').chomp
8
- PKG_FILES = FileList["**/*"].exclude("CVS").exclude("pkg").exclude('coverage')
8
+ PKG_FILES = FileList["**/*"].exclude(/CVS|pkg|coverage/)
9
9
 
10
10
  desc "Installing library"
11
11
  task :install do
12
- dest = CONFIG["sitelibdir"]
13
- install('lib/json.rb', dest)
14
- dest = File.join(dest, 'json')
15
- mkdir_p dest
16
- Dir['lib/json/*.*'].each do |f|
17
- install(f, dest)
18
- end
19
- dest = CONFIG["bindir"]
20
- install('bin/edit_json.rb', dest)
12
+ ruby 'install.rb'
21
13
  end
22
14
 
23
15
  desc "Testing library"
@@ -25,6 +17,10 @@ task :test do
25
17
  ruby 'tests/runner.rb'
26
18
  end
27
19
 
20
+ desc "Testing library with coverage"
21
+ task :coverage do
22
+ system 'rcov -x tests -Ilib tests/runner.rb'
23
+ end
28
24
  desc "Removing generated files"
29
25
  task :clean do
30
26
  rm_rf 'doc'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.2
1
+ 0.4.3
File without changes
@@ -25,7 +25,7 @@
25
25
  # == Examples
26
26
  #
27
27
  # To create a JSON string from a ruby data structure, you
28
- # can call JSON.unparse like that:
28
+ # can call JSON.unparse (or JSON.generate) like that:
29
29
  #
30
30
  # json = JSON.unparse [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
31
31
  # # => "[1,2,{\"a\":3.141},false,true,null,\"4..10\"]"
@@ -86,7 +86,8 @@
86
86
  # JSON.unparse always creates the shortes possible string representation of a
87
87
  # ruby data structure in one line. This good for data storage or network
88
88
  # protocols, but not so good for humans to read. Fortunately there's
89
- # also JSON.pretty_unparse that creates a more readable output:
89
+ # also JSON.pretty_unparse (or JSON.pretty_generate) that creates a more
90
+ # readable output:
90
91
  #
91
92
  # puts JSON.pretty_unparse([1, 2, {"a"=>3.141}, false, true, nil, 4..10])
92
93
  # [
@@ -157,7 +158,9 @@ module JSON
157
158
  UTF16toUTF8 = Iconv.new('utf-8', 'utf-16be')
158
159
  # An iconv instance to convert from UTF16 Big Endian to UTF8.
159
160
  UTF8toUTF16 = Iconv.new('utf-16be', 'utf-8'); UTF8toUTF16.iconv('no bom')
160
- rescue Errno::EINVAL
161
+ rescue Errno::EINVAL, Iconv::InvalidEncoding
162
+ # Iconv doesn't support big endian utf-16. Let's try to hack this manually
163
+ # into the converters.
161
164
  begin
162
165
  old_verbose = $VERBOSE
163
166
  $VERBOSE = nil
@@ -191,7 +194,7 @@ module JSON
191
194
  end
192
195
  UTF16toUTF8 = swapper.new(UTF16toUTF8)
193
196
  end
194
- rescue Errno::EINVAL
197
+ rescue Errno::EINVAL, Iconv::InvalidEncoding
195
198
  # Enforce disabling of unicode support, if iconv doesn't support
196
199
  # UTF8/UTF16 at all.
197
200
  JSON.support_unicode = false
@@ -216,8 +219,8 @@ module JSON
216
219
  # into a Ruby data structure.
217
220
  class Parser < StringScanner
218
221
  STRING = /"((?:[^"\\]|\\.)*)"/
219
- INTEGER = /-?\d+/
220
- FLOAT = /-?\d+\.(\d*)(?i:e[+-]?\d+)?/
222
+ INTEGER = /-?(?:0|[1-9]\d*)/
223
+ FLOAT = /-?(?:0|[1-9]\d*)\.(\d+)(?i:e[+-]?\d+)?/
221
224
  OBJECT_OPEN = /\{/
222
225
  OBJECT_CLOSE = /\}/
223
226
  ARRAY_OPEN = /\[/
@@ -238,7 +241,7 @@ module JSON
238
241
  /(?=\*/) # single slash before this comment's end
239
242
  )*
240
243
  \*/ # the end of this comment
241
- |\s+ # whitespaces
244
+ |[ \t\r\n]+ # whitespaces: space, horicontal tab, lf, cr
242
245
  )+
243
246
  )mx
244
247
 
@@ -248,20 +251,23 @@ module JSON
248
251
  # as a result.
249
252
  def parse
250
253
  reset
254
+ obj = nil
251
255
  until eos?
252
256
  case
253
- when scan(ARRAY_OPEN)
254
- return parse_array
255
257
  when scan(OBJECT_OPEN)
256
- return parse_object
258
+ obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
259
+ obj = parse_object
260
+ when scan(ARRAY_OPEN)
261
+ obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
262
+ obj = parse_array
257
263
  when skip(IGNORE)
258
264
  ;
259
- when !((value = parse_value).equal? UNPARSED)
260
- return value
261
265
  else
262
266
  raise ParserError, "source '#{peek(20)}' not in JSON!"
263
267
  end
264
268
  end
269
+ obj or raise ParserError, "source did not contain any JSON!"
270
+ obj
265
271
  end
266
272
 
267
273
  private
@@ -271,14 +277,14 @@ module JSON
271
277
  return '' if self[1].empty?
272
278
  self[1].gsub(%r(\\(?:[\\bfnrt"/]|u([A-Fa-f\d]{4})))) do
273
279
  case $~[0]
280
+ when '\\"' then '"'
274
281
  when '\\\\' then '\\'
282
+ when '\\/' then '/'
275
283
  when '\\b' then "\b"
276
284
  when '\\f' then "\f"
277
285
  when '\\n' then "\n"
278
286
  when '\\r' then "\r"
279
287
  when '\\t' then "\t"
280
- when '\\"' then '"'
281
- when '\\/' then '/'
282
288
  else
283
289
  if JSON.support_unicode? and $KCODE == 'UTF8'
284
290
  JSON.utf16_to_utf8($~[1])
@@ -297,7 +303,7 @@ module JSON
297
303
  def parse_value
298
304
  case
299
305
  when scan(FLOAT)
300
- Float(self[0])
306
+ Float(self[0].sub(/\.([eE])/, '.0\1'))
301
307
  when scan(INTEGER)
302
308
  Integer(self[0])
303
309
  when scan(TRUE)
@@ -505,6 +511,8 @@ module JSON
505
511
  obj.to_json(JSON::State.from_state(state))
506
512
  end
507
513
 
514
+ alias generate unparse
515
+
508
516
  # Unparse the Ruby data structure _obj_ into a JSON string and return it.
509
517
  # The returned string is a prettier form of the string returned by #unparse.
510
518
  def pretty_unparse(obj)
@@ -516,6 +524,8 @@ module JSON
516
524
  )
517
525
  obj.to_json(state)
518
526
  end
527
+
528
+ alias pretty_generate pretty_unparse
519
529
  end
520
530
 
521
531
  class Object
@@ -681,7 +691,7 @@ module Kernel
681
691
  # one line.
682
692
  def j(*objs)
683
693
  objs.each do |obj|
684
- puts JSON::unparse(obj)
694
+ puts JSON::generate(obj)
685
695
  end
686
696
  nil
687
697
  end
@@ -690,7 +700,7 @@ module Kernel
690
700
  # indentation and over many lines.
691
701
  def jj(*objs)
692
702
  objs.each do |obj|
693
- puts JSON::pretty_unparse(obj)
703
+ puts JSON::pretty_generate(obj)
694
704
  end
695
705
  nil
696
706
  end
@@ -0,0 +1,708 @@
1
+ # = json - JSON library for Ruby
2
+ #
3
+ # == Description
4
+ #
5
+ # == Author
6
+ #
7
+ # Florian Frank <mailto:flori@ping.de>
8
+ #
9
+ # == License
10
+ #
11
+ # This is free software; you can redistribute it and/or modify it under the
12
+ # terms of the GNU General Public License Version 2 as published by the Free
13
+ # Software Foundation: www.gnu.org/copyleft/gpl.html
14
+ #
15
+ # == Download
16
+ #
17
+ # The latest version of this library can be downloaded at
18
+ #
19
+ # * http://rubyforge.org/frs?group_id=953
20
+ #
21
+ # Online Documentation should be located at
22
+ #
23
+ # * http://json.rubyforge.org
24
+ #
25
+ # == Examples
26
+ #
27
+ # To create a JSON string from a ruby data structure, you
28
+ # can call JSON.unparse like that:
29
+ #
30
+ # json = JSON.unparse [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
31
+ # # => "[1,2,{\"a\":3.141},false,true,null,\"4..10\"]"
32
+ #
33
+ # It's also possible to call the #to_json method directly.
34
+ #
35
+ # json = [1, 2, {"a"=>3.141}, false, true, nil, 4..10].to_json
36
+ # # => "[1,2,{\"a\":3.141},false,true,null,\"4..10\"]"
37
+ #
38
+ # To get back a ruby data structure, you have to call
39
+ # JSON.parse on the JSON string:
40
+ #
41
+ # JSON.parse json
42
+ # # => [1, 2, {"a"=>3.141}, false, true, nil, "4..10"]
43
+ #
44
+ # Note, that the range from the original data structure is a simple
45
+ # string now. The reason for this is, that JSON doesn't support ranges
46
+ # or arbitrary classes. In this case the json library falls back to call
47
+ # Object#to_json, which is the same as #to_s.to_json.
48
+ #
49
+ # It's possible to extend JSON to support serialization of arbitray classes by
50
+ # simply implementing a more specialized version of the #to_json method, that
51
+ # should return a JSON object (a hash converted to JSON with #to_json)
52
+ # like this (don't forget the *a for all the arguments):
53
+ #
54
+ # class Range
55
+ # def to_json(*a)
56
+ # {
57
+ # 'json_class' => self.class.name,
58
+ # 'data' => [ first, last, exclude_end? ]
59
+ # }.to_json(*a)
60
+ # end
61
+ # end
62
+ #
63
+ # The hash key 'json_class' is the class, that will be asked to deserialize the
64
+ # JSON representation later. In this case it's 'Range', but any namespace of
65
+ # the form 'A::B' or '::A::B' will do. All other keys are arbitrary and can be
66
+ # used to store the necessary data to configure the object to be deserialized.
67
+ #
68
+ # If a the key 'json_class' is found in a JSON object, the JSON parser checks
69
+ # if the given class responds to the json_create class method. If so, it is
70
+ # called with the JSON object converted to a Ruby hash. So a range can
71
+ # be deserialized by implementing Range.json_create like this:
72
+ #
73
+ # class Range
74
+ # def self.json_create(o)
75
+ # new(*o['data'])
76
+ # end
77
+ # end
78
+ #
79
+ # Now it possible to serialize/deserialize ranges as well:
80
+ #
81
+ # json = JSON.unparse [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
82
+ # # => "[1,2,{\"a\":3.141},false,true,null,{\"json_class\":\"Range\",\"data\":[4,10,false]}]"
83
+ # JSON.parse json
84
+ # # => [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
85
+ #
86
+ # JSON.unparse always creates the shortes possible string representation of a
87
+ # ruby data structure in one line. This good for data storage or network
88
+ # protocols, but not so good for humans to read. Fortunately there's
89
+ # also JSON.pretty_unparse that creates a more readable output:
90
+ #
91
+ # puts JSON.pretty_unparse([1, 2, {"a"=>3.141}, false, true, nil, 4..10])
92
+ # [
93
+ # 1,
94
+ # 2,
95
+ # {
96
+ # "a": 3.141
97
+ # },
98
+ # false,
99
+ # true,
100
+ # null,
101
+ # {
102
+ # "json_class": "Range",
103
+ # "data": [
104
+ # 4,
105
+ # 10,
106
+ # false
107
+ # ]
108
+ # }
109
+ # ]
110
+ #
111
+ # There are also the methods Kernel#j for unparse, and Kernel#jj for
112
+ # pretty_unparse output to the console, that work analogous to Kernel#p and
113
+ # Kernel#pp.
114
+ #
115
+
116
+ require 'strscan'
117
+
118
+ # This module is the namespace for all the JSON related classes. It also
119
+ # defines some module functions to expose a nicer API to users, instead
120
+ # of using the parser and other classes directly.
121
+ module JSON
122
+ # The base exception for JSON errors.
123
+ JSONError = Class.new StandardError
124
+
125
+ # This exception is raise, if a parser error occurs.
126
+ ParserError = Class.new JSONError
127
+
128
+ # This exception is raise, if a unparser error occurs.
129
+ UnparserError = Class.new JSONError
130
+
131
+ # If a circular data structure is encountered while unparsing
132
+ # this exception is raised.
133
+ CircularDatastructure = Class.new UnparserError
134
+
135
+ class << self
136
+ # Switches on Unicode support, if _enable_ is _true_. Otherwise switches
137
+ # Unicode support off.
138
+ def support_unicode=(enable)
139
+ @support_unicode = enable
140
+ end
141
+
142
+ # Returns _true_ if JSON supports unicode, otherwise _false_ is returned.
143
+ #
144
+ # If loading of the iconv library fails, or it doesn't support utf8/utf16
145
+ # encoding, this will be set to false, as a fallback.
146
+ def support_unicode?
147
+ !!@support_unicode
148
+ end
149
+ end
150
+ JSON.support_unicode = true # default, however it's possible to switch off
151
+ # full unicode support, if non-ascii bytes should be
152
+ # just passed through.
153
+
154
+ begin
155
+ require 'iconv'
156
+ # An iconv instance to convert from UTF8 to UTF16 Big Endian.
157
+ UTF16toUTF8 = Iconv.new('utf-8', 'utf-16be')
158
+ # An iconv instance to convert from UTF16 Big Endian to UTF8.
159
+ UTF8toUTF16 = Iconv.new('utf-16be', 'utf-8'); UTF8toUTF16.iconv('no bom')
160
+ rescue Errno::EINVAL
161
+ begin
162
+ old_verbose = $VERBOSE
163
+ $VERBOSE = nil
164
+ # An iconv instance to convert from UTF8 to UTF16 Big Endian.
165
+ UTF16toUTF8 = Iconv.new('utf-8', 'utf-16')
166
+ # An iconv instance to convert from UTF16 Big Endian to UTF8.
167
+ UTF8toUTF16 = Iconv.new('utf-16', 'utf-8'); UTF8toUTF16.iconv('no bom')
168
+ if UTF8toUTF16.iconv("\xe2\x82\xac") == "\xac\x20"
169
+ swapper = Class.new do
170
+ def initialize(iconv)
171
+ @iconv = iconv
172
+ end
173
+
174
+ def iconv(string)
175
+ result = @iconv.iconv(string)
176
+ JSON.swap!(result)
177
+ end
178
+ end
179
+ UTF8toUTF16 = swapper.new(UTF8toUTF16)
180
+ end
181
+ if UTF16toUTF8.iconv("\xac\x20") == "\xe2\x82\xac"
182
+ swapper = Class.new do
183
+ def initialize(iconv)
184
+ @iconv = iconv
185
+ end
186
+
187
+ def iconv(string)
188
+ string = JSON.swap!(string.dup)
189
+ @iconv.iconv(string)
190
+ end
191
+ end
192
+ UTF16toUTF8 = swapper.new(UTF16toUTF8)
193
+ end
194
+ rescue Errno::EINVAL
195
+ # Enforce disabling of unicode support, if iconv doesn't support
196
+ # UTF8/UTF16 at all.
197
+ JSON.support_unicode = false
198
+ ensure
199
+ $VERBOSE = old_verbose
200
+ end
201
+ rescue LoadError
202
+ # Enforce disabling of unicode support, if iconv doesn't exist.
203
+ JSON.support_unicode = false
204
+ end
205
+
206
+ # Swap consecutive bytes in string in place.
207
+ def self.swap!(string)
208
+ 0.upto(string.size / 2) do |i|
209
+ break unless string[2 * i + 1]
210
+ string[2 * i], string[2 * i + 1] = string[2 * i + 1], string[2 * i]
211
+ end
212
+ string
213
+ end
214
+
215
+ # This class implements the JSON parser that is used to parse a JSON string
216
+ # into a Ruby data structure.
217
+ class Parser < StringScanner
218
+ STRING = /"((?:[^"\\]|\\.)*)"/
219
+ INTEGER = /-?\d+/
220
+ FLOAT = /-?\d+\.(\d*)(?i:e[+-]?\d+)?/
221
+ OBJECT_OPEN = /\{/
222
+ OBJECT_CLOSE = /\}/
223
+ ARRAY_OPEN = /\[/
224
+ ARRAY_CLOSE = /\]/
225
+ PAIR_DELIMITER = /:/
226
+ COLLECTION_DELIMITER = /,/
227
+ TRUE = /true/
228
+ FALSE = /false/
229
+ NULL = /null/
230
+ IGNORE = %r(
231
+ (?:
232
+ //[^\n\r]*[\n\r]| # line comments
233
+ /\* # c-style comments
234
+ (?:
235
+ [^*/]| # normal chars
236
+ /[^*]| # slashes that do not start a nested comment
237
+ \*[^/]| # asterisks that do not end this comment
238
+ /(?=\*/) # single slash before this comment's end
239
+ )*
240
+ \*/ # the end of this comment
241
+ |\s+ # whitespaces
242
+ )+
243
+ )mx
244
+
245
+ UNPARSED = Object.new
246
+
247
+ # Parses the current JSON string and returns the complete data structure
248
+ # as a result.
249
+ def parse
250
+ reset
251
+ until eos?
252
+ case
253
+ when scan(ARRAY_OPEN)
254
+ return parse_array
255
+ when scan(OBJECT_OPEN)
256
+ return parse_object
257
+ when skip(IGNORE)
258
+ ;
259
+ when !((value = parse_value).equal? UNPARSED)
260
+ return value
261
+ else
262
+ raise ParserError, "source '#{peek(20)}' not in JSON!"
263
+ end
264
+ end
265
+ end
266
+
267
+ private
268
+
269
+ def parse_string
270
+ if scan(STRING)
271
+ return '' if self[1].empty?
272
+ self[1].gsub(%r(\\(?:[\\bfnrt"/]|u([A-Fa-f\d]{4})))) do
273
+ case $~[0]
274
+ when '\\\\' then '\\'
275
+ when '\\b' then "\b"
276
+ when '\\f' then "\f"
277
+ when '\\n' then "\n"
278
+ when '\\r' then "\r"
279
+ when '\\t' then "\t"
280
+ when '\\"' then '"'
281
+ when '\\/' then '/'
282
+ else
283
+ if JSON.support_unicode? and $KCODE == 'UTF8'
284
+ JSON.utf16_to_utf8($~[1])
285
+ else
286
+ # if utf8 mode is switched off or unicode not supported, try to
287
+ # transform unicode \u-notation to bytes directly:
288
+ $~[1].to_i(16).chr
289
+ end
290
+ end
291
+ end
292
+ else
293
+ UNPARSED
294
+ end
295
+ end
296
+
297
+ def parse_value
298
+ case
299
+ when scan(FLOAT)
300
+ Float(self[0])
301
+ when scan(INTEGER)
302
+ Integer(self[0])
303
+ when scan(TRUE)
304
+ true
305
+ when scan(FALSE)
306
+ false
307
+ when scan(NULL)
308
+ nil
309
+ when (string = parse_string) != UNPARSED
310
+ string
311
+ when scan(ARRAY_OPEN)
312
+ parse_array
313
+ when scan(OBJECT_OPEN)
314
+ parse_object
315
+ else
316
+ UNPARSED
317
+ end
318
+ end
319
+
320
+ def parse_array
321
+ result = []
322
+ until eos?
323
+ case
324
+ when (value = parse_value) != UNPARSED
325
+ result << value
326
+ skip(IGNORE)
327
+ unless scan(COLLECTION_DELIMITER) or match?(ARRAY_CLOSE)
328
+ raise ParserError, "expected ',' or ']' in array at '#{peek(20)}'!"
329
+ end
330
+ when scan(ARRAY_CLOSE)
331
+ break
332
+ when skip(IGNORE)
333
+ ;
334
+ else
335
+ raise ParserError, "unexpected token in array at '#{peek(20)}'!"
336
+ end
337
+ end
338
+ result
339
+ end
340
+
341
+ def parse_object
342
+ result = {}
343
+ until eos?
344
+ case
345
+ when (string = parse_string) != UNPARSED
346
+ skip(IGNORE)
347
+ unless scan(PAIR_DELIMITER)
348
+ raise ParserError, "expected ':' in object at '#{peek(20)}'!"
349
+ end
350
+ skip(IGNORE)
351
+ unless (value = parse_value).equal? UNPARSED
352
+ result[string] = value
353
+ skip(IGNORE)
354
+ unless scan(COLLECTION_DELIMITER) or match?(OBJECT_CLOSE)
355
+ raise ParserError,
356
+ "expected ',' or '}' in object at '#{peek(20)}'!"
357
+ end
358
+ else
359
+ raise ParserError, "expected value in object at '#{peek(20)}'!"
360
+ end
361
+ when scan(OBJECT_CLOSE)
362
+ if klassname = result['json_class']
363
+ klass = klassname.sub(/^:+/, '').split(/::/).inject(Object) do |p,k|
364
+ p.const_get(k) rescue nil
365
+ end
366
+ break unless klass and klass.json_creatable?
367
+ result = klass.json_create(result)
368
+ end
369
+ break
370
+ when skip(IGNORE)
371
+ ;
372
+ else
373
+ raise ParserError, "unexpected token in object at '#{peek(20)}'!"
374
+ end
375
+ end
376
+ result
377
+ end
378
+ end
379
+
380
+ # This class is used to create State instances, that are use to hold data
381
+ # while unparsing a Ruby data structure into a JSON string.
382
+ class State
383
+ # Creates a State object from _opts_, which ought to be Hash to create a
384
+ # new State instance configured by opts, something else to create an
385
+ # unconfigured instance. If _opts_ is a State object, it is just returned.
386
+ def self.from_state(opts)
387
+ case opts
388
+ when self
389
+ opts
390
+ when Hash
391
+ new(opts)
392
+ else
393
+ new
394
+ end
395
+ end
396
+
397
+ # Instantiates a new State object, configured by _opts_.
398
+ def initialize(opts = {})
399
+ @indent = opts[:indent] || ''
400
+ @space = opts[:space] || ''
401
+ @object_nl = opts[:object_nl] || ''
402
+ @array_nl = opts[:array_nl] || ''
403
+ @seen = {}
404
+ end
405
+
406
+ # This string is used to indent levels in the JSON string.
407
+ attr_accessor :indent
408
+
409
+ # This string is used to include a space between the tokens in a JSON
410
+ # string.
411
+ attr_accessor :space
412
+
413
+ # This string is put at the end of a line that holds a JSON object (or
414
+ # Hash).
415
+ attr_accessor :object_nl
416
+
417
+ # This string is put at the end of a line that holds a JSON array.
418
+ attr_accessor :array_nl
419
+
420
+ # Returns _true_, if _object_ was already seen during this Unparsing run.
421
+ def seen?(object)
422
+ @seen.key?(object.__id__)
423
+ end
424
+
425
+ # Remember _object_, to find out if it was already encountered (to find out
426
+ # if a cyclic data structure is unparsed).
427
+ def remember(object)
428
+ @seen[object.__id__] = true
429
+ end
430
+
431
+ # Forget _object_ for this Unparsing run.
432
+ def forget(object)
433
+ @seen.delete object.__id__
434
+ end
435
+ end
436
+
437
+ module_function
438
+
439
+ # Convert _string_ from UTF8 encoding to UTF16 (big endian) encoding and
440
+ # return it.
441
+ def utf8_to_utf16(string)
442
+ JSON::UTF8toUTF16.iconv(string).unpack('H*')[0]
443
+ end
444
+
445
+ # Convert _string_ from UTF16 (big endian) encoding to UTF8 encoding and
446
+ # return it.
447
+ def utf16_to_utf8(string)
448
+ bytes = '' << string[0, 2].to_i(16) << string[2, 2].to_i(16)
449
+ JSON::UTF16toUTF8.iconv(bytes)
450
+ end
451
+
452
+ # Convert a UTF8 encoded Ruby string _string_ to a JSON string, encoded with
453
+ # UTF16 big endian characters as \u????, and return it.
454
+ def utf8_to_json(string)
455
+ i, n, result = 0, string.size, ''
456
+ while i < n
457
+ char = string[i]
458
+ case
459
+ when char == ?\b then result << '\b'
460
+ when char == ?\t then result << '\t'
461
+ when char == ?\n then result << '\n'
462
+ when char == ?\f then result << '\f'
463
+ when char == ?\r then result << '\r'
464
+ when char == ?" then result << '\"'
465
+ when char == ?\\ then result << '\\\\'
466
+ when char == ?/ then result << '\/'
467
+ when char.between?(0x0, 0x1f) then result << "\\u%04x" % char
468
+ when char.between?(0x20, 0x7f) then result << char
469
+ when !(JSON.support_unicode? && $KCODE == 'UTF8')
470
+ # if utf8 mode is switched off or unicode not supported, just pass
471
+ # bytes through:
472
+ result << char
473
+ when char & 0xe0 == 0xc0
474
+ result << '\u' << utf8_to_utf16(string[i, 2])
475
+ i += 1
476
+ when char & 0xf0 == 0xe0
477
+ result << '\u' << utf8_to_utf16(string[i, 3])
478
+ i += 2
479
+ when char & 0xf8 == 0xf0
480
+ result << '\u' << utf8_to_utf16(string[i, 4])
481
+ i += 3
482
+ when char & 0xfc == 0xf8
483
+ result << '\u' << utf8_to_utf16(string[i, 5])
484
+ i += 4
485
+ when char & 0xfe == 0xfc
486
+ result << '\u' << utf8_to_utf16(string[i, 6])
487
+ i += 5
488
+ else
489
+ raise JSON::UnparserError, "Encountered unknown UTF-8 byte: %x!" % char
490
+ end
491
+ i += 1
492
+ end
493
+ result
494
+ end
495
+
496
+ # Parse the JSON string _source_ into a Ruby data structure and return it.
497
+ def parse(source)
498
+ Parser.new(source).parse
499
+ end
500
+
501
+ # Unparse the Ruby data structure _obj_ into a single line JSON string and
502
+ # return it. _state_ is a JSON::State object, that can be used to configure
503
+ # the output further.
504
+ def unparse(obj, state = nil)
505
+ obj.to_json(JSON::State.from_state(state))
506
+ end
507
+
508
+ # Unparse the Ruby data structure _obj_ into a JSON string and return it.
509
+ # The returned string is a prettier form of the string returned by #unparse.
510
+ def pretty_unparse(obj)
511
+ state = JSON::State.new(
512
+ :indent => ' ',
513
+ :space => ' ',
514
+ :object_nl => "\n",
515
+ :array_nl => "\n"
516
+ )
517
+ obj.to_json(state)
518
+ end
519
+ end
520
+
521
+ class Object
522
+ # Converts this object to a string (calling #to_s), converts
523
+ # it to a JSON string, and returns the result. This is a fallback, if no
524
+ # special method #to_json was defined for some object.
525
+ # _state_ is a JSON::State object, that can also be used
526
+ # to configure the produced JSON string output further.
527
+
528
+ def to_json(*) to_s.to_json end
529
+ end
530
+
531
+ class Hash
532
+ # Returns a JSON string containing a JSON object, that is unparsed from
533
+ # this Hash instance.
534
+ # _state_ is a JSON::State object, that can also be used to configure the
535
+ # produced JSON string output further.
536
+ # _depth_ is used to find out nesting depth, to indent accordingly.
537
+ def to_json(state = nil, depth = 0)
538
+ state = JSON::State.from_state(state)
539
+ json_check_circular(state) { json_transform(state, depth) }
540
+ end
541
+
542
+ private
543
+
544
+ def json_check_circular(state)
545
+ if state
546
+ state.seen?(self) and raise JSON::CircularDatastructure,
547
+ "circular data structures not supported!"
548
+ state.remember self
549
+ end
550
+ yield
551
+ ensure
552
+ state and state.forget self
553
+ end
554
+
555
+ def json_shift(state, depth)
556
+ state and not state.object_nl.empty? or return ''
557
+ state.indent * depth
558
+ end
559
+
560
+ def json_transform(state, depth)
561
+ delim = ','
562
+ delim << state.object_nl if state
563
+ result = '{'
564
+ result << state.object_nl if state
565
+ result << map { |key,value|
566
+ json_shift(state, depth + 1) <<
567
+ key.to_s.to_json(state, depth + 1) <<
568
+ ':' << state.space << value.to_json(state, depth + 1)
569
+ }.join(delim)
570
+ result << state.object_nl if state
571
+ result << json_shift(state, depth)
572
+ result << '}'
573
+ result
574
+ end
575
+ end
576
+
577
+ class Array
578
+ # Returns a JSON string containing a JSON array, that is unparsed from
579
+ # this Array instance.
580
+ # _state_ is a JSON::State object, that can also be used to configure the
581
+ # produced JSON string output further.
582
+ # _depth_ is used to find out nesting depth, to indent accordingly.
583
+ def to_json(state = nil, depth = 0)
584
+ state = JSON::State.from_state(state)
585
+ json_check_circular(state) { json_transform(state, depth) }
586
+ end
587
+
588
+ private
589
+
590
+ def json_check_circular(state)
591
+ if state
592
+ state.seen?(self) and raise JSON::CircularDatastructure,
593
+ "circular data structures not supported!"
594
+ state.remember self
595
+ end
596
+ yield
597
+ ensure
598
+ state and state.forget self
599
+ end
600
+
601
+ def json_shift(state, depth)
602
+ state and not state.array_nl.empty? or return ''
603
+ state.indent * depth
604
+ end
605
+
606
+ def json_transform(state, depth)
607
+ delim = ','
608
+ delim << state.array_nl if state
609
+ result = '['
610
+ result << state.array_nl if state
611
+ result << map { |value|
612
+ json_shift(state, depth + 1) << value.to_json(state, depth + 1)
613
+ }.join(delim)
614
+ result << state.array_nl if state
615
+ result << json_shift(state, depth)
616
+ result << ']'
617
+ result
618
+ end
619
+ end
620
+
621
+ class Integer
622
+ # Returns a JSON string representation for this Integer number.
623
+ def to_json(*) to_s end
624
+ end
625
+
626
+ class Float
627
+ # Returns a JSON string representation for this Float number.
628
+ def to_json(*) to_s end
629
+ end
630
+
631
+ class String
632
+ # This string should be encoded with UTF-8 (if JSON unicode support is
633
+ # enabled). A call to this method returns a JSON string
634
+ # encoded with UTF16 big endian characters as \u????. If
635
+ # JSON.support_unicode? is false only control characters are encoded this
636
+ # way, all 8-bit bytes are just passed through.
637
+ def to_json(*)
638
+ '"' << JSON::utf8_to_json(self) << '"'
639
+ end
640
+
641
+ # Raw Strings are JSON Objects (the raw bytes are stored in an array for the
642
+ # key "raw"). The Ruby String can be created by this class method.
643
+ def self.json_create(o)
644
+ o['raw'].pack('C*')
645
+ end
646
+
647
+ # This method creates a raw object, that can be nested into other data
648
+ # structures and will be unparsed as a raw string.
649
+ def to_json_raw_object
650
+ {
651
+ 'json_class' => self.class.name,
652
+ 'raw' => self.unpack('C*'),
653
+ }
654
+ end
655
+
656
+ # This method should be used, if you want to convert raw strings to JSON
657
+ # instead of UTF-8 strings, e. g. binary data (and JSON Unicode support is
658
+ # enabled).
659
+ def to_json_raw(*args)
660
+ to_json_raw_object.to_json(*args)
661
+ end
662
+ end
663
+
664
+ class TrueClass
665
+ # Returns a JSON string for true: 'true'.
666
+ def to_json(*) to_s end
667
+ end
668
+
669
+ class FalseClass
670
+ # Returns a JSON string for false: 'false'.
671
+ def to_json(*) to_s end
672
+ end
673
+
674
+ class NilClass
675
+ # Returns a JSON string for nil: 'null'.
676
+ def to_json(*) 'null' end
677
+ end
678
+
679
+ module Kernel
680
+ # Outputs _objs_ to STDOUT as JSON strings in the shortest form, that is in
681
+ # one line.
682
+ def j(*objs)
683
+ objs.each do |obj|
684
+ puts JSON::unparse(obj)
685
+ end
686
+ nil
687
+ end
688
+
689
+ # Ouputs _objs_ to STDOUT as JSON strings in a pretty format, with
690
+ # indentation and over many lines.
691
+ def jj(*objs)
692
+ objs.each do |obj|
693
+ puts JSON::pretty_unparse(obj)
694
+ end
695
+ nil
696
+ end
697
+ end
698
+
699
+ class Class
700
+ # Returns true, if this class can be used to create an instance
701
+ # from a serialised JSON string. The class has to implement a class
702
+ # method _json_create_ that expects a hash as first parameter, which includes
703
+ # the required data.
704
+ def json_creatable?
705
+ respond_to?(:json_create)
706
+ end
707
+ end
708
+ # vim: set et sw=2 ts=2:
@@ -16,8 +16,11 @@ module JSON
16
16
  # Columns constants
17
17
  ICON_COL, TYPE_COL, CONTENT_COL = 0, 1, 2
18
18
 
19
+ # JSON primitive types (Containers)
20
+ CONTAINER_TYPES = %w[Array Hash].sort
19
21
  # All JSON primitive types
20
- ALL_TYPES = %w[TrueClass FalseClass Numeric String Array Hash NilClass].sort
22
+ ALL_TYPES = (%w[TrueClass FalseClass Numeric String NilClass] +
23
+ CONTAINER_TYPES).sort
21
24
 
22
25
  # The Nodes necessary for the tree representation of a JSON document
23
26
  ALL_NODES = (ALL_TYPES + %w[Key]).sort
@@ -849,7 +852,8 @@ module JSON
849
852
  hbox.add(Label.new("Type:"))
850
853
  hbox.pack_start(type_input = ComboBox.new(true))
851
854
  default_active = 0
852
- ALL_TYPES.each_with_index do |t, i|
855
+ types = parent ? ALL_TYPES : CONTAINER_TYPES
856
+ types.each_with_index do |t, i|
853
857
  type_input.append_text(t)
854
858
  if t == default_type
855
859
  default_active = i
@@ -858,21 +862,21 @@ module JSON
858
862
  type_input.active = default_active
859
863
  dialog.vbox.add(hbox)
860
864
  type_input.signal_connect(:changed) do
861
- configure_value(value_input, ALL_TYPES[type_input.active])
865
+ configure_value(value_input, types[type_input.active])
862
866
  end
863
867
 
864
868
  hbox = HBox.new(false, 5)
865
869
  hbox.add(Label.new("Value:"))
866
870
  hbox.pack_start(value_input = Entry.new)
867
871
  value_input.text = value_text if value_text
868
- configure_value(value_input, ALL_TYPES[type_input.active])
872
+ configure_value(value_input, types[type_input.active])
869
873
 
870
874
  dialog.vbox.add(hbox)
871
875
 
872
876
  dialog.show_all
873
877
  dialog.run do |response|
874
878
  if response == Dialog::RESPONSE_ACCEPT
875
- type = ALL_TYPES[type_input.active]
879
+ type = types[type_input.active]
876
880
  @content = case type
877
881
  when 'Numeric'
878
882
  Integer(value_input.text) rescue Float(value_input.text) rescue 0
@@ -1102,12 +1106,11 @@ module JSON
1102
1106
  if path
1103
1107
  data = Editor.model2data(@treeview.model.iter_first)
1104
1108
  File.open(path + '.tmp', 'wb') do |output|
1105
- json = if @options_menu.pretty_item.active?
1106
- JSON.pretty_unparse(data)
1109
+ if @options_menu.pretty_item.active?
1110
+ output.puts JSON.pretty_generate(data)
1107
1111
  else
1108
- JSON.unparse(data)
1112
+ output.write JSON.unparse(data)
1109
1113
  end
1110
- output.write json
1111
1114
  end
1112
1115
  File.rename path + '.tmp', path
1113
1116
  @filename = path
@@ -10,7 +10,7 @@ require 'test_json'
10
10
 
11
11
  class TS_AllTests
12
12
  def self.suite
13
- suite = Test::Unit::TestSuite.new
13
+ suite = Test::Unit::TestSuite.new name
14
14
  suite << TC_JSON.suite
15
15
  end
16
16
  end
@@ -31,9 +31,13 @@ class TC_JSON < Test::Unit::TestCase
31
31
 
32
32
  def setup
33
33
  $KCODE = 'UTF8'
34
- @ary = [1, "foo", 3.14, 4711.0, 2.718, nil, [1,-2,3], false, true]
34
+ @ary = [1, "foo", 3.14, 4711.0, 2.718, nil, [1,-2,3], false, true].map do
35
+ |x| [x]
36
+ end
35
37
  @ary_to_parse = ["1", '"foo"', "3.14", "4711.0", "2.718", "null",
36
- "[1,-2,3]", "false", "true"]
38
+ "[1,-2,3]", "false", "true"].map do
39
+ |x| "[#{x}]"
40
+ end
37
41
  @hash = {
38
42
  'a' => 2,
39
43
  'b' => 3.141,
@@ -48,15 +52,33 @@ class TC_JSON < Test::Unit::TestCase
48
52
  '"g":"\\"\\u0000\\u001f","h":1.0E3,"i":1.0E-3}'
49
53
  @json2 = '{"a":2,"b":3.141,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},' +
50
54
  '"g":"\\"\\u0000\\u001f","h":1000.0,"i":0.001}'
55
+ @json3 = <<'EOT'.chomp
56
+ {
57
+ "a": 2,
58
+ "b": 3.141,
59
+ "c": "c",
60
+ "d": [
61
+ 1,
62
+ "b",
63
+ 3.14
64
+ ],
65
+ "e": {
66
+ "foo": "bar"
67
+ },
68
+ "g": "\"\u0000\u001f",
69
+ "h": 1000.0,
70
+ "i": 0.001
71
+ }
72
+ EOT
51
73
  end
52
74
 
53
75
  def test_parse_value
54
- assert_equal("", parse('""'))
55
- assert_equal("\\", parse('"\\\\"'))
56
- assert_equal('"', parse('"\""'))
57
- assert_equal('\\"\\', parse('"\\\\\\"\\\\"'))
58
- assert_equal("\\a\"\b\f\n\r\t\0\037",
59
- parse('"\\a\"\b\f\n\r\t\u0000\u001f"'))
76
+ assert_equal([""], parse('[""]'))
77
+ assert_equal(["\\"], parse('["\\\\"]'))
78
+ assert_equal(['"'], parse('["\""]'))
79
+ assert_equal(['\\"\\'], parse('["\\\\\\"\\\\"]'))
80
+ assert_equal(["\\a\"\b\f\n\r\t\0\037"],
81
+ parse('["\\a\"\b\f\n\r\t\u0000\u001f"]'))
60
82
  for i in 0 ... @ary.size
61
83
  assert_equal(@ary[i], parse(@ary_to_parse[i]))
62
84
  end
@@ -68,9 +90,10 @@ class TC_JSON < Test::Unit::TestCase
68
90
  assert_equal([1], parse('[1]'))
69
91
  assert_equal([1], parse(' [ 1 ] '))
70
92
  assert_equal(@ary,
71
- parse('[1,"foo",3.14,47.11e+2,2718.E-3,null,[1,-2,3],false,true]'))
72
- assert_equal(@ary, parse(%Q{ [ 1 , "foo" , 3.14 \t , 47.11e+2
73
- , 2718.E-3 ,\n null , [1, -2, 3 ], false , true\n ] }))
93
+ parse('[[1],["foo"],[3.14],[47.11e+2],[2718.0E-3],[null],[[1,-2,3]]'\
94
+ ',[false],[true]]'))
95
+ assert_equal(@ary, parse(%Q{ [ [1] , ["foo"] , [3.14] \t , [47.11e+2]
96
+ , [2718.0E-3 ],\n[ null] , [[1, -2, 3 ]], [false ],[ true]\n ] }))
74
97
  end
75
98
 
76
99
  def test_parse_object
@@ -85,12 +108,28 @@ class TC_JSON < Test::Unit::TestCase
85
108
  assert_equal(@json2, json)
86
109
  parsed_json = parse(json)
87
110
  assert_equal(@hash, parsed_json)
88
- json = unparse({1=>2})
111
+ json = generate({1=>2})
89
112
  assert_equal('{"1":2}', json)
90
113
  parsed_json = parse(json)
91
114
  assert_equal({"1"=>2}, parsed_json)
92
115
  end
93
116
 
117
+ def test_unparse
118
+ json = pretty_unparse(@hash)
119
+ assert_equal(@json3, json)
120
+ parsed_json = parse(json)
121
+ assert_equal(@hash, parsed_json)
122
+ json = pretty_generate({1=>2})
123
+ assert_equal(<<'EOT'.chomp, json)
124
+ {
125
+ "1": 2
126
+ }
127
+ EOT
128
+ parsed_json = parse(json)
129
+ assert_equal({"1"=>2}, parsed_json)
130
+ end
131
+
132
+
94
133
  def test_parser_reset
95
134
  parser = Parser.new(@json)
96
135
  assert_equal(@hash, parser.parse)
@@ -105,16 +144,16 @@ class TC_JSON < Test::Unit::TestCase
105
144
  assert_equal '" "', ' '.to_json
106
145
  assert_equal "\"#{0x7f.chr}\"", 0x7f.chr.to_json
107
146
  if JSON.support_unicode?
108
- utf8 = '© ≠ €!'
109
- json = '"\u00a9 \u2260 \u20ac!"'
147
+ utf8 = [ '© ≠ €!' ]
148
+ json = '["\u00a9 \u2260 \u20ac!"]'
110
149
  assert_equal json, utf8.to_json
111
150
  assert_equal utf8, parse(json)
112
- utf8 = "\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212"
113
- json = '"\u3042\u3044\u3046\u3048\u304a"'
151
+ utf8 = ["\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212"]
152
+ json = '["\u3042\u3044\u3046\u3048\u304a"]'
114
153
  assert_equal json, utf8.to_json
115
154
  assert_equal utf8, parse(json)
116
- utf8 = 'საქართველო'
117
- json = '"\u10e1\u10d0\u10e5\u10d0\u10e0\u10d7\u10d5\u10d4\u10da\u10dd"'
155
+ utf8 = ['საქართველო']
156
+ json = '["\u10e1\u10d0\u10e5\u10d0\u10e0\u10d7\u10d5\u10d4\u10da\u10dd"]'
118
157
  assert_equal json, utf8.to_json
119
158
  assert_equal utf8, parse(json)
120
159
  else
@@ -164,7 +203,7 @@ EOT
164
203
 
165
204
  def test_extended_json
166
205
  a = A.new(666)
167
- json = a.to_json
206
+ json = generate(a)
168
207
  a_again = JSON.parse(json)
169
208
  assert_kind_of a.class, a_again
170
209
  assert_equal a, a_again
@@ -196,35 +235,53 @@ EOT
196
235
  return
197
236
  end
198
237
  $KCODE = 'NONE'
199
- utf8 = "© ≠ €! - \001"
200
- json = "\"© ≠ €! - \\u0001\""
201
- assert_equal json, utf8.to_json
238
+ utf8 = ["© ≠ €! - \001"]
239
+ json = "[\"© ≠ €! - \\u0001\"]"
240
+ assert_equal json, generate(utf8)
202
241
  assert_equal utf8, parse(json)
203
242
  assert JSON.support_unicode?
204
243
  $KCODE = 'UTF8'
205
- utf8 = '© ≠ €!'
206
- json = '"\u00a9 \u2260 \u20ac!"'
207
- assert_equal json, utf8.to_json
244
+ utf8 = ['© ≠ €!']
245
+ json = '["\u00a9 \u2260 \u20ac!"]'
246
+ assert_equal json, unparse(utf8)
208
247
  assert_equal utf8, parse(json)
209
248
  JSON.support_unicode = false
210
249
  assert !JSON.support_unicode?
211
- utf8 = "© ≠ €! - \001"
212
- json = "\"© ≠ €! - \\u0001\""
213
- assert_equal json, utf8.to_json
250
+ utf8 = ["© ≠ €! - \001"]
251
+ json = "[\"© ≠ €! - \\u0001\"]"
252
+ assert_equal json, unparse(utf8)
214
253
  assert_equal utf8, parse(json)
215
254
  end
216
255
 
217
256
  def test_backslash
218
- json = '"\\\\.(?i:gif|jpe?g|png)$"'
257
+ json = '["\\\\.(?i:gif|jpe?g|png)$"]'
219
258
  data = JSON.parse(json)
220
259
  assert_equal json, JSON.unparse(data)
221
- json = '"\\""'
260
+ json = '["\\""]'
222
261
  data = JSON.parse(json)
223
262
  assert_equal json, JSON.unparse(data)
224
- json = '"\/"'
263
+ json = '["\/"]'
225
264
  data = JSON.parse(json)
226
- assert_equal '/', data
265
+ assert_equal ['/'], data
227
266
  assert_equal json, JSON.unparse(data)
228
267
  end
268
+
269
+ def test_wrong_inputs
270
+ assert_raises(ParserError) { JSON.parse('"foo"') }
271
+ assert_raises(ParserError) { JSON.parse('123') }
272
+ assert_raises(ParserError) { JSON.parse('[] bla') }
273
+ assert_raises(ParserError) { JSON.parse('[] 1') }
274
+ assert_raises(ParserError) { JSON.parse('[] []') }
275
+ assert_raises(ParserError) { JSON.parse('[] {}') }
276
+ assert_raises(ParserError) { JSON.parse('{} []') }
277
+ assert_raises(ParserError) { JSON.parse('{} {}') }
278
+ assert_raises(ParserError) { JSON.parse('[NULL]') }
279
+ assert_raises(ParserError) { JSON.parse('[FALSE]') }
280
+ assert_raises(ParserError) { JSON.parse('[TRUE]') }
281
+ assert_raises(ParserError) { JSON.parse('[07] ') }
282
+ assert_raises(ParserError) { JSON.parse('[0a]') }
283
+ assert_raises(ParserError) { JSON.parse('[1.]') }
284
+ assert_raises(ParserError) { JSON.parse(' ') }
285
+ end
229
286
  end
230
287
  # vim: set et sw=2 ts=2:
metadata CHANGED
@@ -1,10 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.8.11
2
+ rubygems_version: 0.9.0
3
3
  specification_version: 1
4
4
  name: json
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.4.2
7
- date: 2006-08-25 00:00:00 +02:00
6
+ version: 0.4.3
7
+ date: 2007-02-10 00:00:00 +01:00
8
8
  summary: A JSON implementation in Ruby
9
9
  require_paths:
10
10
  - lib
@@ -25,6 +25,7 @@ required_ruby_version: !ruby/object:Gem::Version::Requirement
25
25
  platform: ruby
26
26
  signing_key:
27
27
  cert_chain:
28
+ post_install_message:
28
29
  authors:
29
30
  - Florian Frank
30
31
  files:
@@ -35,12 +36,14 @@ files:
35
36
  - GPL
36
37
  - install.rb
37
38
  - Rakefile
39
+ - bla.json.tmp
38
40
  - lib
39
41
  - README
40
42
  - CHANGES
41
43
  - bin/edit_json.rb
42
44
  - tests/runner.rb
43
45
  - tests/test_json.rb
46
+ - lib/json.rb.orig
44
47
  - lib/json
45
48
  - lib/json.rb
46
49
  - lib/json/FalseClass.xpm