diff --git a/Gemfile b/Gemfile index c80529ac3d9..70a21e3ec49 100644 --- a/Gemfile +++ b/Gemfile @@ -25,6 +25,7 @@ gem 'net-ssh' gem 'netaddr', '>= 2.0.4' gem 'newrelic_rpm' gem 'nokogiri', '>=1.10.5' +gem 'oj' gem 'palm_civet' gem 'posix-spawn', '~> 0.3.15' gem 'protobuf', '3.6.12' diff --git a/Gemfile.lock b/Gemfile.lock index 0a10b254db4..4f56cb139f7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -308,6 +308,7 @@ GEM racc (~> 1.4) nokogiri (1.12.4-x86_64-linux) racc (~> 1.4) + oj (3.13.2) os (1.0.1) palm_civet (1.1.0) parallel (1.20.1) @@ -552,6 +553,7 @@ DEPENDENCIES netaddr (>= 2.0.4) newrelic_rpm nokogiri (>= 1.10.5) + oj palm_civet parallel_tests pg diff --git a/config/initializers/json.rb b/config/initializers/json.rb index 03d4eee48e2..627915a3b4d 100644 --- a/config/initializers/json.rb +++ b/config/initializers/json.rb @@ -1,7 +1,15 @@ require 'active_support/json/encoding' module CCInitializers - def self.json(_cc_config) + def self.json(cc_config) + if cc_config[:use_optimized_json_encoder] + MultiJson.use(:oj) + Oj::Rails.optimize # Use optimized encoders instead of as_json() methods for available classes. + Oj.default_options = { + bigdecimal_load: :bigdecimal, + } + end + ActiveSupport.json_encoder = Class.new do attr_reader :options @@ -10,10 +18,16 @@ def initialize(options=nil) end def encode(value) + if MultiJson.default_adapter == :oj && value.is_a?(VCAP::CloudController::Presenters::V3::BasePresenter) + v = value.to_hash + else + v = value.as_json(options.dup) + end + if Rails.env.test? - MultiJson.dump(value.as_json(options.dup)) + MultiJson.dump(v) else - MultiJson.dump(value.as_json(options.dup), options.merge(pretty: true)) + MultiJson.dump(v, options.merge(pretty: true)) end end end diff --git a/lib/cloud_controller/config_schemas/base/api_schema.rb b/lib/cloud_controller/config_schemas/base/api_schema.rb index f572fd92bd6..fd74704a245 100644 --- a/lib/cloud_controller/config_schemas/base/api_schema.rb +++ b/lib/cloud_controller/config_schemas/base/api_schema.rb @@ -350,6 +350,8 @@ class ApiSchema < VCAP::Config write_key: String, dataset: String, }, + + optional(:use_optimized_json_encoder) => bool, } end # rubocop:enable Metrics/BlockLength diff --git a/lib/cloud_controller/http_response_error.rb b/lib/cloud_controller/http_response_error.rb index e9f9cc799aa..1ca1fe15495 100644 --- a/lib/cloud_controller/http_response_error.rb +++ b/lib/cloud_controller/http_response_error.rb @@ -10,6 +10,9 @@ def initialize(message, method, response) begin source = MultiJson.load(response.body) + rescue ArgumentError + # Either Oj should raise Oj::ParseError instead of ArgumentError, or MultiJson should also wrap + # ArgumentError into MultiJson::Adapters::Oj::ParseError rescue MultiJson::ParseError source = response.body end