使用oj gem解析时的回调

时间:2017-07-27 13:37:25

标签: ruby-on-rails json ruby

我想了解在使用Oj解析JSON文件时如何理解在每个键上应用转换(在我的情况下是下划线)的方法。

例如在ruby / rails中:

require 'oj'
Oj.optimize_rails()

def transform_keys(hash)
  hash.deep_transform_keys { |k| k.to_s.underscore }
end

data = '{ "JsonKey": "JsonValue", "JsonKey2": { "JsonSubKey2": "JsonSubValue" }, "Array": ["ValueArray1","ValueArray2"] }'
data2 = '[{ "JsonKey": "JsonValue", "JsonKey2": { "JsonSubKey2": "JsonSubValue" }, "Array": ["ValueArray1","ValueArray2"] }]'

json_data = JSON.parse(data)

case json_data
when Hash
  transform_keys(json_data)
when Array
  json_data.map { |hash| transform_keys(hash) }
end

这可以完成这项任务,但它会迭代两次:一次解析并应用转换。

检查oj,我发现:

试试吧:

class UnderscoreKeyHandler < ::Oj::ScHandler
  def hash_start
    {}
  end

  def hash_set(h,k,v)
    h[k.to_s.underscore] = v
  end

  def array_start
    []
  end

  def array_append(a,v)
    a << v
  end

  def add_value(v)
  end
end
handler = UnderscoreKeyHandler.new
Oj.sc_parse(handler, data)

有效!好吧,让我们对此进行基准测试:

require 'oj'
Oj.optimize_rails()
hash = Hash.new
key = 'abcd'
1000.times { hash[key.succ!] = hash.keys }
json = hash.to_json; nil

def transform_keys(hash)
  hash.deep_transform_keys { |k| k.to_s.underscore }
end


10000 * Benchmark.realtime { 
  json_data = JSON.parse(json)
  case json_data
  when Hash
    transform_keys(json_data)
  when Array
    json_data.map { |hash| transform_keys(hash) }
  end
} # Between 2400 and 3500

10000 * Benchmark.realtime { Oj.sc_parse(handler, json) } # Between 700 and 1600

完美?我似乎是,但我感到不安全......

实际上我只想覆盖哈希的每个键而不是重写完整的处理程序。有办法吗?

此外:

  • :: Oj :: ScHandler和:: Oj :: Saj之间有什么区别?
  • 使用自定义处理程序的风险是什么
  • add_value方法的目的是什么。
  • 如何引发另一个错误而不是Oj :: ParseError默认错误?

0 个答案:

没有答案