Rya*_*chi 7 json iterator scala stream jerkson
我需要能够处理大型JSON文件,从可反序列化的子字符串中实例化对象,因为我们正在迭代/流式传输文件.
例如:
假设我只能反序列化为以下实例:
case class Data(val a: Int, val b: Int, val c: Int)
Run Code Online (Sandbox Code Playgroud)
和预期的JSON格式是:
{ "foo": [ {"a": 0, "b": 0, "c": 0 }, {"a": 0, "b": 0, "c": 1 } ],
"bar": [ {"a": 1, "b": 0, "c": 0 }, {"a": 1, "b": 0, "c": 1 } ],
.... MANY ITEMS .... ,
"qux": [ {"a": 0, "b": 0, "c": 0 } }
Run Code Online (Sandbox Code Playgroud)
我会喜欢做的是:
import com.codahale.jerkson.Json
val dataSeq : Seq[Data] = Json.advanceToValue("foo").stream[Data](fileStream)
// NOTE: this will not compile since I pulled the "advanceToValue" out of thin air.
Run Code Online (Sandbox Code Playgroud)
作为最后一点,我更愿意找到一个涉及Jerkson或Play框架附带的任何其他库的解决方案,但如果另一个Scala库更轻松,更好地处理这个场景:我不反对尝试另一个库.如果有一种干净的方式手动搜索文件,然后使用Json库继续从那里解析:我没关系.
我确实不希望做的是摄取整个文件,而不流或使用迭代器,如在同一时间保持整个文件在内存中是非常昂贵的.
这是我当前解决问题的方法:
import collection.immutable.PagedSeq
import util.parsing.input.PagedSeqReader
import com.codahale.jerkson.Json
import collection.mutable
private def fileContent = new PagedSeqReader(PagedSeq.fromFile("/home/me/data.json"))
private val clearAndStop = ']'
private def takeUntil(readerInitial: PagedSeqReader, text: String) : Taken = {
val str = new StringBuilder()
var readerFinal = readerInitial
while(!readerFinal.atEnd && !str.endsWith(text)) {
str += readerFinal.first
readerFinal = readerFinal.rest
}
if (!str.endsWith(text) || str.contains(clearAndStop))
Taken(readerFinal, None)
else
Taken(readerFinal, Some(str.toString))
}
private def takeUntil(readerInitial: PagedSeqReader, chars: Char*) : Taken = {
var taken = Taken(readerInitial, None)
chars.foreach(ch => taken = takeUntil(taken.reader, ch.toString))
taken
}
def getJsonData() : Seq[Data] = {
var data = mutable.ListBuffer[Data]()
var taken = takeUntil(fileContent, "\"foo\"")
taken = takeUntil(taken.reader, ':', '[')
var doneFirst = false
while(taken.text != None) {
if (!doneFirst)
doneFirst = true
else
taken = takeUntil(taken.reader, ',')
taken = takeUntil(taken.reader, '}')
if (taken.text != None) {
print(taken.text.get)
places += Json.parse[Data](taken.text.get)
}
}
data
}
case class Taken(reader: PagedSeqReader, text: Option[String])
case class Data(val a: Int, val b: Int, val c: Int)
Run Code Online (Sandbox Code Playgroud)
当然,这段代码并不能非常干净地处理格式错误的 JSON,并且要用于多个顶级键“foo”、“bar”和“qux”,需要向前查看(或从可能的顶级键列表中进行匹配) ),但总的来说:我相信这可以完成工作。它不像我想要的那样功能强大,也不是超级强大,但 PagedSeqReader 绝对可以防止它变得太混乱。
| 归档时间: |
|
| 查看次数: |
2414 次 |
| 最近记录: |