使用动态数据解析非常大的JSON文件



我需要解析从服务器下载的非常大的JSON文件。这些JSON文件可以包含完全不同的键和值。以下是一些例子。。。

{ "result": "PASS", 
"items": [ 
{ "name": "John", "age": 33 }, 
{ "name": "Jane", "age": 23 } ] 
}

{ "result": "PASS", 
"items": [ 
{ "make": "Ford", "model": "Mustang", "colors": ["blue", "red", "silver"] }, 
{ "make": "Dodge", "model": "Charger", "colors": ["yellow", "black", "silver"] } ] 
}

items数组可能包含数千个条目,每个条目中的数据最多可包含60个键/值对。

这只是两个例子,但我需要能够解析30-40个不同类型的JSON文件,而且我不能总是控制文件中的数据类型。因此,我无法创建自定义模型来将数据绑定到应用程序中的对象。

我要做的是为items数组中的每个项创建一个JsonObject,并将其添加到我可以在应用程序中使用的MutableList中。我目前正在使用Klaxon Streaming API来尝试实现这一点,但似乎可以找到一种方法来实现这一目标,而无需绑定到自定义对象。

JsonReader(StringReader(testJson)).use { reader ->
reader.beginObject {
var result: String? = null
while (reader.hasNext()) {
val name = reader.nextName()
when (name) {
"result" -> result = reader.nextString()
"items" -> {
reader.beginArray {
while (reader.hasNext()) {
// ???
}
}
}
}
}
}
}

如果您打算以任何方式将所有项目收集到列表中(而不是立即一个接一个地处理它们(,那么使用流式API没有多大意义。它可以做得简单得多:

val response = Klaxon().parseJsonObject(StringReader(testJson))
val result = response["result"]
val items = response.array<JsonObject>("items") ?: JsonArray()
...

流式处理涉及更多。首先,您需要确保,在开始处理之前,服务器响应不会完全读取到内存中(即,解析器输入不应该是字符串,而应该是输入流。详细信息取决于您选择的http客户端库(。其次,您需要提供某种回调,以便在项目到达时对其进行处理,例如:

fun parse(input: Reader, onResult: (String) -> Unit, onItem: (JsonObject) -> Unit)  {
JsonReader(input).use { reader ->
reader.beginObject {
while (reader.hasNext()) {
when (reader.nextName()) {
"result" -> onResult(reader.nextString())
"items" -> reader.beginArray {
while (reader.hasNext()) {
val item = Parser(passedLexer = reader.lexer, streaming = true).parse(reader) as JsonObject
onItem(item)
}
}
}
}
}
}
}
fun main(args: Array<String>) {
// "input" simulates the server response 
val input = ByteArrayInputStream(testJson.encodeToByteArray())
InputStreamReader(input).use {
parse(it,
onResult = { println("""Result: $it""") },
onItem = { println(it.asIterable().joinToString(", ")) }
)
}
}

更好的方法是将Klaxon与Kotlin Flow或Sequence集成,但我发现这很困难,因为beginObject和beginArray包装器不能很好地处理suspend函数。

最新更新