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