2

我需要从 json 文件(大约 2G 大小)中过滤掉一些数据。乔恩就像

{ "dataName": "staff",
  "version": 5,
  "data": [
    {"name":"Fred",
    "team":"football",
    "hobby":"climbing"
    },
     {"name":"Tony",
     "team":"basketball",
     "hobby":"fishing"},

    {"name":"alex",
      "team":"soccer",
      "hobby":"movies"
    }
  ]
}

在做了一些关于在 ruby​​ 中解析巨大 json 的研究之后,我找到了https://github.com/dgraham/json-streamhttps://github.com/brianmario/yajl-ruby,我尝试了 json_stream 大约需要 20 分钟,并且这个网站https://github.com/dgraham/yajl-ffi#performance

yajl-ruby 更快

使用 json_stream,我可以使用诸如 start_object/end_object/key/value 之类的回调来了解何时解析对象,然后对该对象进行一些处理并继续。

但是使用 yajl-ruby,我只找到一个名为“on_parse_complete”的回调。它的文档(https://www.rubydoc.info/github/brianmario/yajl-ruby/Yajl/Parser)说

"#on_parse_complete= ⇒ Object
call-seq: on_parse_complete = Proc.new { |obj| … }

This callback setter allows you to pass a Proc/lambda or any other object that responds to #call.

#It will pass a single parameter, the ruby object built from the last parsed JSON object"#

然后我写了一段代码


require 'yajl'
def parse_farquaad f, chunk_size
   parser = Yajl::Parser.new

    parser.on_parse_complete = Proc.new do |obj|
      yield obj
    end

    f.each(chunk_size) { |chunk| parser << chunk }
  end

  File.open("big_file.json") do |f|
      parse_farquaad f, 8092 do |current_data_unit|
        puts "obj is:"
        puts current_data_unit
  end

我测试了小尺寸的样本 json 文件(

见开头给出的例子

)

但输出是#the whole JSON obj#(一次全部转储),而不是我想要的是逐个输出“数据”部分中的每个对象,就像我可以在“数据”中的每个obj之后得到json流一样" 被解析并输出,我可以对它做一些事情,比如检查每个 obj 是否是我想要的数据。

我的预期输出是:

起初,obj { "name":"Fred", "team":"football", "hobby":"climbing" } 在这个 obj 上做某事

然后 obj {"name":"Tony", "team":"basketball", "hobby":"fishing"} 在这个 obj 上做某事

然后 obj {"name":"alex", "team":"soccer", "hobby":"movies" } 在这个 obj 上做某事.....

可能我对这句话有一些误解

"它将传递一个参数,即从最后解析的 JSON 对象构建的 ruby​​ 对象"#

关于回调

“on_parse_complete”

在上面显示的文档中描述。

任何人都知道如何用 yajl-ruby 做到这一点?任何帮助表示赞赏。

4

0 回答 0