1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

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 "coffee-script"
gem "sass", ">= 3.0" gem "sass", ">= 3.0"
gem "multi_json", :git => 'git://github.com/intridea/multi_json.git'
gem "rake", ">= 0.8.7" gem "rake", ">= 0.8.7"
gem "mocha", ">= 0.9.8" 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/attribute_accessors'
require 'active_support/core_ext/module/delegation' require 'active_support/core_ext/module/delegation'
require 'multi_json'
module ActiveSupport module ActiveSupport
# Look for and parse json strings that look like ISO 8601 times. # Look for and parse json strings that look like ISO 8601 times.
mattr_accessor :parse_json_times mattr_accessor :parse_json_times
module JSON module JSON
# Listed in order of preference.
DECODERS = %w(Yajl Yaml)
class << self class << self
attr_reader :parse_error def decode(json, options ={})
delegate :decode, :to => :backend data = MultiJson.decode(json, options)
if ActiveSupport.parse_json_times
def backend convert_dates_from(data)
set_default_backend unless defined?(@backend)
@backend
end
def backend=(name)
if name.is_a?(Module)
@backend = name
else else
require "active_support/json/backends/#{name.to_s.downcase}" data
@backend = ActiveSupport::JSON::Backends::const_get(name)
end end
@parse_error = @backend::ParseError
end end
def engine
MultiJson.engine
end
alias :backend :engine
def engine=(name)
MultiJson.engine = name
end
alias :backend= :engine=
def with_backend(name) def with_backend(name)
old_backend, self.backend = backend, name old_backend, self.backend = backend, name
yield yield
@ -35,15 +34,26 @@ module ActiveSupport
self.backend = old_backend self.backend = old_backend
end end
def set_default_backend private
DECODERS.find do |name|
def convert_dates_from(data)
case data
when nil
nil
when DATE_REGEX
begin begin
self.backend = name DateTime.parse(data)
true rescue ArgumentError
rescue LoadError data
# Try next decoder.
false
end 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

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