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:
parent
3e33592316
commit
e019587e31
6 changed files with 40 additions and 235 deletions
2
Gemfile
2
Gemfile
|
@ -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"
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue