我正在尝试解析从mongoDB实例返回的JSON对象,并且在解析文档ID时遇到问题。请参见下面的示例响应:
{
"type_id":"zyxwv54321",
"content":{
"contentsA":{
"abcd123":{ },
"efgh123":{ },
"ijkl123":{ },
"mnop123":{ },
"qrst123":{ },
"uvwx123":{ },
"yzab123":{ }
},
"contentsB":{
"abcd123":{ },
"efgh123":{ },
"ijkl123":{ },
"mnop123":{ },
"qrst123":{ },
"uvwx123":{ },
"yzab123":{ }
}
},
"manager":"mail@mail.com"
}
问题出在contentsA
和contentsB
中的对象,我该如何解析这些对象?这些对象中包含的每个字符串都是唯一的ID,该ID会发生变化,因此鉴于这些键的未知性质,很难获得数据模型类。
答案 0 :(得分:0)
您将需要实现自己的自定义序列化器/反序列化器,以解析具有动态键值的JSON。它不会很漂亮,但是并不可怕。并且实际上在性能方面提供了几个优势:
使用GSON(但是实际上任何库在概念上都是相似的),您需要在解析算法+ implement a custom TypeAdapter中描述您的对象,以便您的网络调用可以返回填充的数据模型类。像这样:
val jsonReader = JsonReader(inputStream.reader())
jsonReader.isLenient = true //I recommend reading up on this flag
jsonReader.beginObject()
parseInternals(jsonReader)
jsonReader.endObject()
现在,在您的parseInternal
函数中,您需要在响应流传输时浏览各个字段,并检查JsonToken类型(它是一个枚举)
fun parseInternals(jsonReader: JsonReader): YourDataModel {
//check there are still tokens to parse in your JSON
val yourDataModel = YourDataModel()
while (jsonReader.hasNext()) {
//name is a key in your JSON
if (jsonReader.peek() == JsonToken.NAME) {
val fieldName = jsonReader.readName()
if (fieldName == "type_id") {
dataModel.typeId = jsonReader.nextString()
}
//and so on until you populate your data model class
}
}
}
您的下一个令牌将是 content ,它是从另一个对象开始的,因此您需要手动执行jsonReader.begin/endObject()
,直到获得那些动态nextName
在您的解析器中。确保使用jsonReader.peek()
继续检查下一个令牌的类型,并将其与您期望的令牌进行比较。
在编写解析器之后,为其编写一些单元测试,以确保它正在执行您期望的功能。如果JSON模式发生更改,这将有助于将来的证明,以便您尽早发现它。