diff --git a/.gitignore b/.gitignore index 763cc5a2..385f5fef 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,9 @@ tmtags ## VIM *.swp +## IDEA +.idea + ## PROJECT::GENERAL .yardoc coverage diff --git a/Rakefile b/Rakefile index 9af21d7a..004a85ed 100644 --- a/Rakefile +++ b/Rakefile @@ -18,6 +18,7 @@ end task :spec => %w[ base_spec + adapters:fast_jsonparser adapters:oj adapters:yajl adapters:json_gem diff --git a/benchmark.rb b/benchmark.rb index 1dd89cd1..670652ce 100644 --- a/benchmark.rb +++ b/benchmark.rb @@ -1,4 +1,8 @@ +libx = File.expand_path("../lib", __FILE__) +$LOAD_PATH.unshift(libx) unless $LOAD_PATH.include?(libx) + require 'oj' +require 'fast_jsonparser' require 'multi_json' require 'benchmark/ips' @@ -7,5 +11,13 @@ Benchmark.ips do |x| x.time = 10 x.warmup = 1 - x.report { MultiJson.load(MultiJson.dump(a: 1, b: 2, c: 3)) } + x.report("oj") { MultiJson.load(MultiJson.dump(a: 1, b: 2, c: 3)) } +end + +MultiJson.use :fast_jsonparser + +Benchmark.ips do |x| + x.time = 10 + x.warmup = 1 + x.report("fast_jsonparser") { MultiJson.load(MultiJson.dump(a: 1, b: 2, c: 3)) } end diff --git a/lib/multi_json.rb b/lib/multi_json.rb index 5909370d..a83b35f7 100644 --- a/lib/multi_json.rb +++ b/lib/multi_json.rb @@ -31,6 +31,7 @@ def default_options ALIASES = {'jrjackson' => 'jr_jackson'} REQUIREMENT_MAP = [ + [:fast_jsonparser, 'fast_jsonparser'], [:oj, 'oj'], [:yajl, 'yajl'], [:jr_jackson, 'jrjackson'], @@ -44,6 +45,7 @@ def default_options # if any adapters are already loaded, then checks # to see which are installed if none are loaded. def default_adapter + return :fast_jsonparser if defined?(::FastJsonparser) return :oj if defined?(::Oj) return :yajl if defined?(::Yajl) return :jr_jackson if defined?(::JrJackson) @@ -79,6 +81,7 @@ def adapter # Set the JSON parser utilizing a symbol, string, or class. # Supported by default are: # + # * :fast_jsonparser # * :oj # * :json_gem # * :json_pure diff --git a/lib/multi_json/adapters/fast_jsonparser.rb b/lib/multi_json/adapters/fast_jsonparser.rb new file mode 100644 index 00000000..42e70dd5 --- /dev/null +++ b/lib/multi_json/adapters/fast_jsonparser.rb @@ -0,0 +1,44 @@ +require 'fast_jsonparser' +require 'oj' +require 'multi_json/adapter' + +module MultiJson + module Adapters + # Use the Oj library to dump/load. + class FastJsonparser < Adapter + defaults :load, :symbolize_keys => false + defaults :dump, :mode => :compat, :time_format => :ruby, :use_to_json => true + + ParseError = ::FastJsonparser::Error + + def load(string, options = {}) + ::FastJsonparser.parse(string, options) + end + + case ::Oj::VERSION + when /\A2\./ + def dump(object, options = {}) + options.merge!(:indent => 2) if options[:pretty] + options[:indent] = options[:indent].to_i if options[:indent] + ::Oj.dump(object, options) + end + when /\A3\./ + PRETTY_STATE_PROTOTYPE = { + :indent => " ", + :space => " ", + :space_before => "", + :object_nl => "\n", + :array_nl => "\n", + :ascii_only => false, + } + + def dump(object, options = {}) + options.merge!(PRETTY_STATE_PROTOTYPE.dup) if options.delete(:pretty) + ::Oj.dump(object, options) + end + else + fail "Unsupported Oj version: #{::Oj::VERSION}" + end + end + end +end diff --git a/spec/fast_jsonparser_adapter_spec.rb b/spec/fast_jsonparser_adapter_spec.rb new file mode 100644 index 00000000..d349fb22 --- /dev/null +++ b/spec/fast_jsonparser_adapter_spec.rb @@ -0,0 +1,10 @@ +require 'spec_helper' + +exit 0 if skip_adapter?('fast_jsonparser') + +require 'shared/adapter' +require 'multi_json/adapters/fast_jsonparser' + +describe MultiJson::Adapters::FastJsonparser do + it_behaves_like 'an adapter', described_class +end