最好使用Circe和Akka流进行流JSON解码

时间:2018-07-19 11:31:55

标签: json akka-stream circe

我的用例与this entry相似,希望从JSON对象中读取内部的巨大数组(文本为数GB):

{ "a": "...",   // root level fields to be read, separately
  ...
  "bs": [       // the huge array, most of the payload (can be multiple GB's)
    {...},
    ...
  ]
}

输入可用Source[ByteString,_](Akka流)提供,我在其他地方使用Circe进行JSON解码。

我可以看到两个挑战:

  1. 以流方式读取bs数组(获取Source[B,_]以供使用)。

  2. 将原始流拆分为两个,因此我可以在数组开始之前读取和分析根级别字段。

您是否有解决此类用例的指南?到目前为止,我已经检查了akka-stream-jsoncirce-iteratee

akka-stream-json看起来很像,但维护得不是很好。   circe-iteratee似乎没有与Akka Streams集成。

2 个答案:

答案 0 :(得分:1)

Jawn有一个异步解析器:https://github.com/non/jawn/blob/master/parser/src/main/scala/jawn/AsyncParser.scala

但是由于其顺序来源,很难为JSON编写高效的异步解析器。

如果可以切换到同步解析,则可以使用jsoniter-scala-core并编写一个简单的自定义编解码器,该编解码器将跳过除“ bs”之外的所有不需要的键/值对,然后快速解析所需的数据而无需保持或在内存中排列内容。

答案 1 :(得分:0)

我看到这需要一个全新的库,用于流JSON解码。

类似的东西:

case class A(a: Int, bs: Source[B,_])

val src: Source[ByteString,_] = ???
src.as[A]

我的临时解决方案是通过jqsed“按摩” JSON,以便每个B都在自己的行上。这样,我就可以逐行使用源代码并分别解码每个B

这是Bash脚本(不保证):

#!/bin/bash

arrKey=$1
input=$2

head -n 1 $input | sed s/.$//
jq -M -c ".$arrKey|.[]" $input | sed s/$/,/
echo "]}"

它确实依赖某些东西,例如非数组问题始终位于第一行。