如何使用NeoJSON解析Pharo中的ndjson

时间:2016-01-20 15:41:41

标签: json stream smalltalk pharo ndjson

我想在Pharo Smalltalk上用ndjson解析NeoJSON(换行符分隔的json)数据。

ndjson数据如下所示:

{"smalltalk": "cool"}
{"pharo": "cooler"}

目前我将文件流转换为字符串,将其拆分为换行符,然后使用NeoJSON解析单个部分。这似乎使用了不必要的(并且非常巨大的)内存和时间量,可能是因为将流转换为字符串,反之亦然。什么是有效的方法来完成这项任务?

如果您要查找示例数据:NYPL-publicdomain: pd_items_1.ndjson

3 个答案:

答案 0 :(得分:3)

这是Sven(NeoJSON的作者)在pharo-users邮件列表中的答案(他不是在SO上):

阅读'格式'很简单,只需继续为每个JSON表达式执行#next(忽略空格)。

| data reader |
data := '{"smalltalk": "cool"}
{"pharo": "cooler"}'.
reader := NeoJSONReader on: data readStream.
Array streamContents: [ :out |
  [ reader atEnd ] whileFalse: [ out nextPut: reader next ] ].

防止中间数据结构也很容易,使用流媒体。

| client reader data networkStream |
(client := ZnClient new)
  streaming: true;
  url: 'https://github.com/NYPL-publicdomain/data-and-utilities/blob/master/items/pd_items_1.ndjson?raw=true';
  get.
networkStream := ZnCharacterReadStream on: client contents.
reader := NeoJSONReader on: networkStream.
data := Array streamContents: [ :out |
  [ reader atEnd ] whileFalse: [ out nextPut: reader next ] ].
client close.
data.

花了几秒钟,毕竟50K以上的网络是80MB +。

答案 1 :(得分:2)

如果您打开一个新的ReadWriteStream,首先将$ {写入其中,然后将用逗号分隔的原始流的所有内容流式传输到它上,然后写一个尾随的$},它会起作用吗?结果流应该对NeoJSON有用......? 这可能是针对这个问题的STTCPW攻击,但W很重要;-)而且它应该更快,耗费更少的内存,因为NeoJSON只会做一次通过..

只是一个想法,没有尝试过。

答案 2 :(得分:1)

您可以尝试这样的事情:

| input reader |
input := FileStream readOnlyFileNamed: 'resources/pd_items_1.ndjson.txt'.
[ 
Array
    streamContents: [ :strm | 
        | ln |
        [ (ln := input nextLine) isNil ] 
          whileFalse: [ strm nextPut: (NeoJSONReader fromString: ln) ] ] ] timeToRun.

除非你已经尝试过这个......