From e019587e31abe66416c0b5d26b6ac177b345a727 Mon Sep 17 00:00:00 2001 From: Josh Kalderimis Date: Mon, 18 Apr 2011 21:39:15 +0200 Subject: removed AS backends and instead rely on MultiJson for json decoding --- Gemfile | 2 + .../lib/active_support/json/backends/jsongem.rb | 47 --------- .../lib/active_support/json/backends/yajl.rb | 44 -------- .../lib/active_support/json/backends/yaml.rb | 113 --------------------- activesupport/lib/active_support/json/decoding.rb | 56 +++++----- activesupport/test/json/decoding_test.rb | 11 +- 6 files changed, 39 insertions(+), 234 deletions(-) delete mode 100644 activesupport/lib/active_support/json/backends/jsongem.rb delete mode 100644 activesupport/lib/active_support/json/backends/yajl.rb delete mode 100644 activesupport/lib/active_support/json/backends/yaml.rb diff --git a/Gemfile b/Gemfile index c720b09a2c..0b6de3061f 100644 --- a/Gemfile +++ b/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" diff --git a/activesupport/lib/active_support/json/backends/jsongem.rb b/activesupport/lib/active_support/json/backends/jsongem.rb deleted file mode 100644 index 533ba25da3..0000000000 --- a/activesupport/lib/active_support/json/backends/jsongem.rb +++ /dev/null @@ -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 diff --git a/activesupport/lib/active_support/json/backends/yajl.rb b/activesupport/lib/active_support/json/backends/yajl.rb deleted file mode 100644 index 58818658c7..0000000000 --- a/activesupport/lib/active_support/json/backends/yajl.rb +++ /dev/null @@ -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 diff --git a/activesupport/lib/active_support/json/backends/yaml.rb b/activesupport/lib/active_support/json/backends/yaml.rb deleted file mode 100644 index e25e29d36b..0000000000 --- a/activesupport/lib/active_support/json/backends/yaml.rb +++ /dev/null @@ -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 - diff --git a/activesupport/lib/active_support/json/decoding.rb b/activesupport/lib/active_support/json/decoding.rb index c1f6330c6c..ac99f180a5 100644 --- a/activesupport/lib/active_support/json/decoding.rb +++ b/activesupport/lib/active_support/json/decoding.rb @@ -1,32 +1,31 @@ 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 decode(json, options ={}) + data = MultiJson.decode(json, options) + if ActiveSupport.parse_json_times + convert_dates_from(data) + else + data + end + end - def backend - set_default_backend unless defined?(@backend) - @backend + def engine + MultiJson.engine end + alias :backend :engine - def backend=(name) - if name.is_a?(Module) - @backend = name - else - require "active_support/json/backends/#{name.to_s.downcase}" - @backend = ActiveSupport::JSON::Backends::const_get(name) - end - @parse_error = @backend::ParseError + def engine=(name) + MultiJson.engine = name end + alias :backend= :engine= def with_backend(name) old_backend, self.backend = backend, name @@ -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 diff --git a/activesupport/test/json/decoding_test.rb b/activesupport/test/json/decoding_test.rb index 88cf97de7e..0e6772e284 100644 --- a/activesupport/test/json/decoding_test.rb +++ b/activesupport/test/json/decoding_test.rb @@ -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 -- cgit v1.2.3 From 1d8be7bc6f098b829ac14ef457af688043975ddc Mon Sep 17 00:00:00 2001 From: Josh Kalderimis Date: Tue, 19 Apr 2011 00:01:50 +0200 Subject: AS Json parse_error makes a return for backwards compatibility, although it will return MultiJson::DecodeError --- activesupport/lib/active_support/json/decoding.rb | 4 ++++ activesupport/test/json/decoding_test.rb | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/json/decoding.rb b/activesupport/lib/active_support/json/decoding.rb index ac99f180a5..cbeb6c0a28 100644 --- a/activesupport/lib/active_support/json/decoding.rb +++ b/activesupport/lib/active_support/json/decoding.rb @@ -34,6 +34,10 @@ module ActiveSupport self.backend = old_backend end + def parse_error + MultiJson::DecodeError + end + private def convert_dates_from(data) diff --git a/activesupport/test/json/decoding_test.rb b/activesupport/test/json/decoding_test.rb index 0e6772e284..6ccffa59b1 100644 --- a/activesupport/test/json/decoding_test.rb +++ b/activesupport/test/json/decoding_test.rb @@ -82,7 +82,7 @@ class TestJSONDecoding < ActiveSupport::TestCase end def test_failed_json_decoding - assert_raise(MultiJson::DecodeError) { ActiveSupport::JSON.decode(%({: 1})) } + assert_raise(ActiveSupport::JSON.parse_error) { ActiveSupport::JSON.decode(%({: 1})) } end end -- cgit v1.2.3 From b24621809ebd4c69796b5ca6b41e7720bc52228a Mon Sep 17 00:00:00 2001 From: Josh Kalderimis Date: Tue, 19 Apr 2011 16:34:34 +0200 Subject: remove MultiJson from the Gemfile and instead add the current rc to the AS gemspec --- Gemfile | 2 -- activesupport/activesupport.gemspec | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index 0b6de3061f..c720b09a2c 100644 --- a/Gemfile +++ b/Gemfile @@ -15,8 +15,6 @@ 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" diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec index eaecb30090..968d6ff4d0 100644 --- a/activesupport/activesupport.gemspec +++ b/activesupport/activesupport.gemspec @@ -16,4 +16,6 @@ Gem::Specification.new do |s| s.files = Dir['CHANGELOG', 'README.rdoc', 'lib/**/*'] s.require_path = 'lib' + + s.add_dependency('multi_json', '~> 1.0.0.rc3') end -- cgit v1.2.3