removed AS backends and instead rely on MultiJson for json decoding

This commit is contained in:
Josh Kalderimis 2011-04-18 21:39:15 +02:00
parent 3e33592316
commit e019587e31
6 changed files with 40 additions and 235 deletions

View File

@ -15,6 +15,8 @@ gem "sprockets", :git => "git://github.com/sstephenson/sprockets.git"
gem "coffee-script"
gem "sass", ">= 3.0"
gem "multi_json", :git => 'git://github.com/intridea/multi_json.git'
gem "rake", ">= 0.8.7"
gem "mocha", ">= 0.9.8"

View File

@ -1,47 +0,0 @@
require 'json' unless defined?(JSON)
module ActiveSupport
module JSON
module Backends
module JSONGem
ParseError = ::JSON::ParserError
extend self
# Parses a JSON string or IO and convert it into an object
def decode(json)
if json.respond_to?(:read)
json = json.read
end
data = ::JSON.parse(json)
if ActiveSupport.parse_json_times
convert_dates_from(data)
else
data
end
end
private
def convert_dates_from(data)
case data
when nil
nil
when DATE_REGEX
begin
DateTime.parse(data)
rescue ArgumentError
data
end
when Array
data.map! { |d| convert_dates_from(d) }
when Hash
data.each do |key, value|
data[key] = convert_dates_from(value)
end
else
data
end
end
end
end
end
end

View File

@ -1,44 +0,0 @@
require 'yajl' unless defined?(Yajl)
module ActiveSupport
module JSON
module Backends
module Yajl
ParseError = ::Yajl::ParseError
extend self
# Parses a JSON string or IO and convert it into an object
def decode(json)
data = ::Yajl::Parser.new.parse(json)
if ActiveSupport.parse_json_times
convert_dates_from(data)
else
data
end
end
private
def convert_dates_from(data)
case data
when nil
nil
when DATE_REGEX
begin
DateTime.parse(data)
rescue ArgumentError
data
end
when Array
data.map! { |d| convert_dates_from(d) }
when Hash
data.each do |key, value|
data[key] = convert_dates_from(value)
end
else
data
end
end
end
end
end
end

View File

@ -1,113 +0,0 @@
require 'active_support/core_ext/string/starts_ends_with'
module ActiveSupport
module JSON
module Backends
module Yaml
ParseError = ::StandardError
extend self
EXCEPTIONS = [::ArgumentError] # :nodoc:
begin
require 'psych'
EXCEPTIONS << Psych::SyntaxError
rescue LoadError
end
# Parses a JSON string or IO and converts it into an object
def decode(json)
if json.respond_to?(:read)
json = json.read
end
YAML.load(convert_json_to_yaml(json))
rescue *EXCEPTIONS => e
raise ParseError, "Invalid JSON string: '%s'" % json
end
protected
# Ensure that ":" and "," are always followed by a space
def convert_json_to_yaml(json) #:nodoc:
require 'strscan' unless defined? ::StringScanner
scanner, quoting, marks, pos, times = ::StringScanner.new(json), false, [], nil, []
while scanner.scan_until(/(\\['"]|['":,\\]|\\.|[\]])/)
case char = scanner[1]
when '"', "'"
if !quoting
quoting = char
pos = scanner.pos
elsif quoting == char
if valid_date?(json[pos..scanner.pos-2])
# found a date, track the exact positions of the quotes so we can
# overwrite them with spaces later.
times << pos
end
quoting = false
end
when ":",",", "]"
marks << scanner.pos - 1 unless quoting
when "\\"
scanner.skip(/\\/)
end
end
if marks.empty?
json.gsub(/\\([\\\/]|u[[:xdigit:]]{4})/) do
ustr = $1
if ustr.start_with?('u')
char = [ustr[1..-1].to_i(16)].pack("U")
# "\n" needs extra escaping due to yaml formatting
char == "\n" ? "\\n" : char
elsif ustr == '\\'
'\\\\'
else
ustr
end
end
else
left_pos = [-1].push(*marks)
right_pos = marks << scanner.pos + scanner.rest_size
output = []
left_pos.each_with_index do |left, i|
scanner.pos = left.succ
chunk = scanner.peek(right_pos[i] - scanner.pos + 1)
if ActiveSupport.parse_json_times
# overwrite the quotes found around the dates with spaces
while times.size > 0 && times[0] <= right_pos[i]
chunk.insert(times.shift - scanner.pos - 1, '! ')
end
end
chunk.gsub!(/\\([\\\/]|u[[:xdigit:]]{4})/) do
ustr = $1
if ustr.start_with?('u')
char = [ustr[1..-1].to_i(16)].pack("U")
# "\n" needs extra escaping due to yaml formatting
char == "\n" ? "\\n" : char
elsif ustr == '\\'
'\\\\'
else
ustr
end
end
output << chunk
end
output = output * " "
output.gsub!(/\\\//, '/')
output
end
end
private
def valid_date?(date_string)
begin
date_string =~ DATE_REGEX && DateTime.parse(date_string)
rescue ArgumentError
false
end
end
end
end
end
end

View File

@ -1,33 +1,32 @@
require 'active_support/core_ext/module/attribute_accessors'
require 'active_support/core_ext/module/delegation'
require 'multi_json'
module ActiveSupport
# Look for and parse json strings that look like ISO 8601 times.
mattr_accessor :parse_json_times
module JSON
# Listed in order of preference.
DECODERS = %w(Yajl Yaml)
class << self
attr_reader :parse_error
delegate :decode, :to => :backend
def backend
set_default_backend unless defined?(@backend)
@backend
end
def backend=(name)
if name.is_a?(Module)
@backend = name
def decode(json, options ={})
data = MultiJson.decode(json, options)
if ActiveSupport.parse_json_times
convert_dates_from(data)
else
require "active_support/json/backends/#{name.to_s.downcase}"
@backend = ActiveSupport::JSON::Backends::const_get(name)
data
end
@parse_error = @backend::ParseError
end
def engine
MultiJson.engine
end
alias :backend :engine
def engine=(name)
MultiJson.engine = name
end
alias :backend= :engine=
def with_backend(name)
old_backend, self.backend = backend, name
yield
@ -35,15 +34,26 @@ module ActiveSupport
self.backend = old_backend
end
def set_default_backend
DECODERS.find do |name|
private
def convert_dates_from(data)
case data
when nil
nil
when DATE_REGEX
begin
self.backend = name
true
rescue LoadError
# Try next decoder.
false
DateTime.parse(data)
rescue ArgumentError
data
end
when Array
data.map! { |d| convert_dates_from(d) }
when Hash
data.each do |key, value|
data[key] = convert_dates_from(value)
end
else
data
end
end
end

View File

@ -56,12 +56,9 @@ class TestJSONDecoding < ActiveSupport::TestCase
%q({"a":"Line1\u000aLine2"}) => {"a"=>"Line1\nLine2"}
}
# load the default JSON backend
ActiveSupport::JSON.backend = 'Yaml'
backends = %w(Yaml)
backends << "JSONGem" if defined?(::JSON)
backends << "Yajl" if defined?(::Yajl)
backends = [:ok_json]
backends << :json_gem if defined?(::JSON)
backends << :yajl if defined?(::Yajl)
backends.each do |backend|
TESTS.each do |json, expected|
@ -85,7 +82,7 @@ class TestJSONDecoding < ActiveSupport::TestCase
end
def test_failed_json_decoding
assert_raise(ActiveSupport::JSON.parse_error) { ActiveSupport::JSON.decode(%({: 1})) }
assert_raise(MultiJson::DecodeError) { ActiveSupport::JSON.decode(%({: 1})) }
end
end