3

考虑以下场景,我需要将很多大哈希放入数组中,然后将其转换为 json:

hash1 = { ... big hash ... }
hash2 = { ... big hash ... }
hash3 = { ... big hash ... }
array = [hash1, hash2, hash3]

json = JSON.dump(array)

问题是从这些哈希生成 json 需要很长时间,所以我想缓存它。但是,我不能缓存整个数组,只能缓存单独的项目。显然,将缓存的 json 字符串放入数组会产生不好的结果:

hash1 = {:a => 1}
hash1json = JSON.dump(hash1)
array = [hash1json]
JSON.generate(array)
==> ["{\"a\":1}"]

当我需要的时候

==> [{"a":1}]

我能想到的唯一方法是做这样的事情:

"[#{[hash1json].join(",")}]"
==> [{"a":1}]

对于这种特定情况,这可能就足够了,但是如果想要缓存一些深层结构而不是简单的数组,那就更难了。

4

2 回答 2

2

事实证明这实际上非常简单:

class CachedJson
  def initialize(str)
    @str = str
  end

  def to_json
    @str
  end
end

puts Yajl::Encoder.encode(:data => [{:a => 1}, '{"b":2}'])
# => {"data":[{"a":1},"{\"b\":2}"]}

puts Yajl::Encoder.encode(:data => [{:a => 1}, CachedJson.new('{"b":2}')])
# => {"data":[{"a":1},{"b":2}]}

在引擎盖下 yajl 调用to_json每个对象,并且此方法必须返回字符串,因此只需将缓存的 json 字符串与CachedJson对象包装起来

于 2013-04-23T22:37:35.103 回答
0

编辑

我之前的回答完全错过了问题的性能方面(对此感到抱歉),所以这是我的发现。也许它可以帮助你一点。

显然,在这些情况下,使用yajl 库yajl-ruby的绑定C似乎可以在进行转换时提高性能。例如,这里我正在生成一个带有10,000条目的哈希:

  require 'json'
  require 'yajl'
  require 'benchmark'
  tmp = "" 
  10000.times do |i|
   tmp += "\"#{i}\" => \"#{i}\", " 
  end

 domains = eval("{#{tmp}}")

 puts "JSON DUMP #{Benchmark.measure { JSON.dump(domains) }} "

 puts "Yajl::Encoder #{Benchmark.measure { Yajl::Encoder.encode(domains)}}"

这些是结果:

JSON DUMP   0.010000   0.000000   0.010000 (  0.007495)

Yajl::Encoder   0.000000   0.000000   0.000000 (  0.003542)

我始终将转换为 json 的任务的时间减半。希望能帮助到你!

于 2013-03-07T21:03:04.747 回答