问题
json = Yajl::Parser.parse(file_stream)
当你像这样调用 Yajl::Parser 时,整个流被加载到内存中以创建你的数据结构。不要那样做。
解决方案
Yajl 提供Parser#parse_chunk、Parser#on_parse_complete和其他相关方法,使您能够在流上触发解析事件,而无需一次解析整个 IO 流。自述文件包含一个如何使用分块的示例。
自述文件中给出的示例是:
或者假设您无权访问包含 JSON 数据的 IO 对象,而是一次只能访问其中的块。没问题!
(假设我们在 EventMachine::Connection 实例中)
def post_init
@parser = Yajl::Parser.new(:symbolize_keys => true)
end
def object_parsed(obj)
puts "Sometimes one pays most for the things one gets for nothing. - Albert Einstein"
puts obj.inspect
end
def connection_completed
# once a full JSON object has been parsed from the stream
# object_parsed will be called, and passed the constructed object
@parser.on_parse_complete = method(:object_parsed)
end
def receive_data(data)
# continue passing chunks
@parser << data
end
或者,如果您不需要流式传输它,它只会在完成后从解析中返回构建的对象。注意:如果输入中有多个 JSON 字符串,您必须指定一个块或回调,因为这是 yajl-ruby 在解析输入时将每个对象交给您(调用者)的方式。
obj = Yajl::Parser.parse(str_or_io)
无论哪种方式,您一次只能解析 JSON 数据的一个子集。否则,您只是在内存中实例化一个巨大的哈希,这正是您描述的行为。
如果不知道您的数据是什么样的以及您的 JSON 对象是如何组成的,那么不可能给出比这更详细的解释;因此,您的里程可能会有所不同。但是,这至少应该让您指出正确的方向。