lib/json.rb in json-0.4.2 vs lib/json.rb in json-0.4.3
- old
+ new
@@ -23,11 +23,11 @@
# * http://json.rubyforge.org
#
# == Examples
#
# To create a JSON string from a ruby data structure, you
-# can call JSON.unparse like that:
+# can call JSON.unparse (or JSON.generate) like that:
#
# json = JSON.unparse [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
# # => "[1,2,{\"a\":3.141},false,true,null,\"4..10\"]"
#
# It's also possible to call the #to_json method directly.
@@ -84,11 +84,12 @@
# # => [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
#
# JSON.unparse always creates the shortes possible string representation of a
# ruby data structure in one line. This good for data storage or network
# protocols, but not so good for humans to read. Fortunately there's
-# also JSON.pretty_unparse that creates a more readable output:
+# also JSON.pretty_unparse (or JSON.pretty_generate) that creates a more
+# readable output:
#
# puts JSON.pretty_unparse([1, 2, {"a"=>3.141}, false, true, nil, 4..10])
# [
# 1,
# 2,
@@ -155,11 +156,13 @@
require 'iconv'
# An iconv instance to convert from UTF8 to UTF16 Big Endian.
UTF16toUTF8 = Iconv.new('utf-8', 'utf-16be')
# An iconv instance to convert from UTF16 Big Endian to UTF8.
UTF8toUTF16 = Iconv.new('utf-16be', 'utf-8'); UTF8toUTF16.iconv('no bom')
- rescue Errno::EINVAL
+ rescue Errno::EINVAL, Iconv::InvalidEncoding
+ # Iconv doesn't support big endian utf-16. Let's try to hack this manually
+ # into the converters.
begin
old_verbose = $VERBOSE
$VERBOSE = nil
# An iconv instance to convert from UTF8 to UTF16 Big Endian.
UTF16toUTF8 = Iconv.new('utf-8', 'utf-16')
@@ -189,11 +192,11 @@
@iconv.iconv(string)
end
end
UTF16toUTF8 = swapper.new(UTF16toUTF8)
end
- rescue Errno::EINVAL
+ rescue Errno::EINVAL, Iconv::InvalidEncoding
# Enforce disabling of unicode support, if iconv doesn't support
# UTF8/UTF16 at all.
JSON.support_unicode = false
ensure
$VERBOSE = old_verbose
@@ -214,12 +217,12 @@
# This class implements the JSON parser that is used to parse a JSON string
# into a Ruby data structure.
class Parser < StringScanner
STRING = /"((?:[^"\\]|\\.)*)"/
- INTEGER = /-?\d+/
- FLOAT = /-?\d+\.(\d*)(?i:e[+-]?\d+)?/
+ INTEGER = /-?(?:0|[1-9]\d*)/
+ FLOAT = /-?(?:0|[1-9]\d*)\.(\d+)(?i:e[+-]?\d+)?/
OBJECT_OPEN = /\{/
OBJECT_CLOSE = /\}/
ARRAY_OPEN = /\[/
ARRAY_CLOSE = /\]/
PAIR_DELIMITER = /:/
@@ -236,51 +239,54 @@
/[^*]| # slashes that do not start a nested comment
\*[^/]| # asterisks that do not end this comment
/(?=\*/) # single slash before this comment's end
)*
\*/ # the end of this comment
- |\s+ # whitespaces
+ |[ \t\r\n]+ # whitespaces: space, horicontal tab, lf, cr
)+
)mx
UNPARSED = Object.new
# Parses the current JSON string and returns the complete data structure
# as a result.
def parse
reset
+ obj = nil
until eos?
case
- when scan(ARRAY_OPEN)
- return parse_array
when scan(OBJECT_OPEN)
- return parse_object
+ obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
+ obj = parse_object
+ when scan(ARRAY_OPEN)
+ obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
+ obj = parse_array
when skip(IGNORE)
;
- when !((value = parse_value).equal? UNPARSED)
- return value
else
raise ParserError, "source '#{peek(20)}' not in JSON!"
end
end
+ obj or raise ParserError, "source did not contain any JSON!"
+ obj
end
private
def parse_string
if scan(STRING)
return '' if self[1].empty?
self[1].gsub(%r(\\(?:[\\bfnrt"/]|u([A-Fa-f\d]{4})))) do
case $~[0]
+ when '\\"' then '"'
when '\\\\' then '\\'
+ when '\\/' then '/'
when '\\b' then "\b"
when '\\f' then "\f"
when '\\n' then "\n"
when '\\r' then "\r"
when '\\t' then "\t"
- when '\\"' then '"'
- when '\\/' then '/'
else
if JSON.support_unicode? and $KCODE == 'UTF8'
JSON.utf16_to_utf8($~[1])
else
# if utf8 mode is switched off or unicode not supported, try to
@@ -295,11 +301,11 @@
end
def parse_value
case
when scan(FLOAT)
- Float(self[0])
+ Float(self[0].sub(/\.([eE])/, '.0\1'))
when scan(INTEGER)
Integer(self[0])
when scan(TRUE)
true
when scan(FALSE)
@@ -503,10 +509,12 @@
# the output further.
def unparse(obj, state = nil)
obj.to_json(JSON::State.from_state(state))
end
+ alias generate unparse
+
# Unparse the Ruby data structure _obj_ into a JSON string and return it.
# The returned string is a prettier form of the string returned by #unparse.
def pretty_unparse(obj)
state = JSON::State.new(
:indent => ' ',
@@ -514,10 +522,12 @@
:object_nl => "\n",
:array_nl => "\n"
)
obj.to_json(state)
end
+
+ alias pretty_generate pretty_unparse
end
class Object
# Converts this object to a string (calling #to_s), converts
# it to a JSON string, and returns the result. This is a fallback, if no
@@ -679,19 +689,19 @@
module Kernel
# Outputs _objs_ to STDOUT as JSON strings in the shortest form, that is in
# one line.
def j(*objs)
objs.each do |obj|
- puts JSON::unparse(obj)
+ puts JSON::generate(obj)
end
nil
end
# Ouputs _objs_ to STDOUT as JSON strings in a pretty format, with
# indentation and over many lines.
def jj(*objs)
objs.each do |obj|
- puts JSON::pretty_unparse(obj)
+ puts JSON::pretty_generate(obj)
end
nil
end
end