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

Android 使用动态数据解析非常大的JSON文件,android,json,kotlin,klaxon,Android,Json,Kotlin,Klaxon,我需要解析从服务器下载的非常大的JSON文件。这些JSON文件可以包含完全不同的键和值。这里有一些例子 { "result": "PASS", "items": [ { "name": "John", "age": 33 }, { "name": "Jane", "age": 23 } ]

我需要解析从服务器下载的非常大的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结果=响应[“结果”]
val items=response.array(“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(", ")) }
        )
    }
}
fun解析(输入:Reader,onResult:(String)->Unit,onItem:(JsonObject)->Unit){
JsonReader(输入)。使用{reader->
reader.beginObject{
while(reader.hasNext()){
何时(reader.nextName()){
“result”->onResult(reader.nextString())
“items”->reader.beginArray{
while(reader.hasNext()){
val item=Parser(passedLexer=reader.lexer,streaming=true)
反恐怖主义(项目)
}
}
}
}
}
}
}
趣味主线(args:Array){
//“输入”模拟服务器响应
val input=ByteArrayInputStream(testJson.encodeToByteArray())
InputStreamReader(输入)。使用{
解析(它,
onResult={println(“'Result:$it”“”)},
onItem={println(it.asIterable().joinToString(“,”)}
)
}
}
然而,将Klaxon与Kotlin流或序列集成会更好,但我发现这很困难,因为beginObject和beginArray包装器不能很好地与挂起函数配合使用