Make our own fast MultiToJson
This commit is contained in:
parent
b717ffeccf
commit
d4b6216ff3
90
lib/fast_jsonapi/multi_to_json.rb
Normal file
90
lib/fast_jsonapi/multi_to_json.rb
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
# Usage:
|
||||||
|
# class Movie
|
||||||
|
# def to_json(payload)
|
||||||
|
# FastJsonapi::MultiToJson.to_json(payload)
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
module FastJsonapi
|
||||||
|
module MultiToJson
|
||||||
|
# Result object pattern is from https://johnnunemaker.com/resilience-in-ruby/
|
||||||
|
# e.g. https://github.com/github/github-ds/blob/fbda5389711edfb4c10b6c6bad19311dfcb1bac1/lib/github/result.rb
|
||||||
|
class Result
|
||||||
|
def initialize(*rescued_exceptions)
|
||||||
|
rescued_exceptions = [StandardError] if rescued_exceptions.empty?
|
||||||
|
@value = yield
|
||||||
|
@error = nil
|
||||||
|
rescue *rescued_exceptions => e
|
||||||
|
@error = e
|
||||||
|
end
|
||||||
|
|
||||||
|
def ok?
|
||||||
|
@error.nil?
|
||||||
|
end
|
||||||
|
|
||||||
|
def value!
|
||||||
|
if ok?
|
||||||
|
@value
|
||||||
|
else
|
||||||
|
raise @error
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def rescue
|
||||||
|
return self if ok?
|
||||||
|
Result.new { yield(@error) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.logger(device=nil)
|
||||||
|
return @logger = Logger.new(device) if device
|
||||||
|
@logger ||= Logger.new(IO::NULL)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Encoder-compatible with default MultiJSON adapters and defaults
|
||||||
|
def self.to_json_method
|
||||||
|
encode_method = String.new(%(def _fast_to_json(object)\n ))
|
||||||
|
encode_method << Result.new(LoadError) {
|
||||||
|
require 'oj'
|
||||||
|
%(::Oj.dump(object, mode: :compat, time_format: :ruby, use_to_json: true))
|
||||||
|
}.rescue {
|
||||||
|
require 'yajl'
|
||||||
|
%(::Yajl::Encoder.encode(object))
|
||||||
|
}.rescue {
|
||||||
|
require 'jrjackson' unless defined?(::JrJackson)
|
||||||
|
%(::JrJackson::Json.dump(object))
|
||||||
|
}.rescue {
|
||||||
|
require 'json'
|
||||||
|
%(JSON.fast_generate(object, create_additions: false, quirks_mode: true))
|
||||||
|
}.rescue {
|
||||||
|
require 'gson'
|
||||||
|
%(::Gson::Encoder.new({}).encode(object))
|
||||||
|
}.rescue {
|
||||||
|
require 'active_support/json/encoding'
|
||||||
|
%(::ActiveSupport::JSON.encode(object))
|
||||||
|
}.rescue {
|
||||||
|
warn "No JSON encoder found. Falling back to `object.to_json`"
|
||||||
|
%(object.to_json)
|
||||||
|
}.value!
|
||||||
|
encode_method << "\nend"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.to_json(object)
|
||||||
|
_fast_to_json(object)
|
||||||
|
rescue NameError
|
||||||
|
define_to_json(FastJsonapi::MultiToJson)
|
||||||
|
_fast_to_json(object)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.define_to_json(receiver)
|
||||||
|
cl = caller_locations[0]
|
||||||
|
method_body = to_json_method
|
||||||
|
logger.debug { "Defining #{receiver}._fast_to_json as #{method_body.inspect}" }
|
||||||
|
receiver.instance_eval method_body, cl.absolute_path, cl.lineno
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.reset_to_json!
|
||||||
|
undef :_fast_to_json if method_defined?(:_fast_to_json)
|
||||||
|
logger.debug { "Undefining #{receiver}._fast_to_json" }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -1,4 +1,5 @@
|
|||||||
require 'active_support/concern'
|
require 'active_support/concern'
|
||||||
|
require 'fast_jsonapi/multi_to_json'
|
||||||
|
|
||||||
module FastJsonapi
|
module FastJsonapi
|
||||||
module SerializationCore
|
module SerializationCore
|
||||||
@ -67,7 +68,7 @@ module FastJsonapi
|
|||||||
|
|
||||||
# Override #to_json for alternative implementation
|
# Override #to_json for alternative implementation
|
||||||
def to_json(payload)
|
def to_json(payload)
|
||||||
JSON.fast_generate(payload) if payload.present?
|
FastJsonapi::MultiToJson.to_json(payload) if payload.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
# includes handler
|
# includes handler
|
||||||
|
Loading…
x
Reference in New Issue
Block a user