如何用Moshi与Kotlin转换混合类型JSON数组?遇解析异常求助
解决Moshi解析混合类型JSON数组的报错问题
错误原因
你遇到的com.squareup.moshi.JsonDataException: Expected a string but was BEGIN_OBJECT at path错误,核心问题在于JSON的rows字段是混合类型的数组数组:每个子数组里既有字符串,又有嵌套对象。默认Moshi适配器无法自动处理这种固定位置的混合结构,若你在数据类里把第二个元素定义为String类型,就会和实际的对象结构产生解析冲突。
最优解决方案:自定义适配器映射强类型结构
不用@RawValue(会丢失类型安全),通过自定义Moshi适配器,把混合数组映射到强类型数据类中,既保证类型安全,又能正常解析。
步骤1:定义对应的数据类
根据JSON结构定义强类型数据类:
// 顶层响应类 data class SummaryResponse( val summary: Summary ) // 包含rows的嵌套类 data class Summary( val rows: List<RowItem> ) // 对应每个子数组的结构 data class RowItem( val date: String, val item: Item, val test1: String, val test2: String ) // 子数组中的嵌套对象 data class Item( val name: String, val index: Int )
步骤2:编写RowItem的自定义适配器
创建适配器处理数组与RowItem的双向转换:
class RowItemAdapter { @FromJson fun fromJson(reader: JsonReader): RowItem { reader.beginArray() // 按JSON子数组的顺序读取元素 val date = reader.nextString() val item = reader.readValue<Item>() val test1 = reader.nextString() val test2 = reader.nextString() reader.endArray() return RowItem(date, item, test1, test2) } @ToJson fun toJson(writer: JsonWriter, value: RowItem) { // 序列化时还原为数组结构 writer.beginArray() writer.value(value.date) writer.value(value.item) writer.value(value.test1) writer.value(value.test2) writer.endArray() } }
步骤3:初始化Moshi并注册适配器
创建Moshi实例时添加自定义适配器,即可正常解析:
val moshi = Moshi.Builder() .add(RowItemAdapter()) .build() // 解析JSON字符串 val adapter = moshi.adapter(SummaryResponse::class.java) val response = adapter.fromJson(yourJsonString)
备选方案:手动解析List(临时场景可用)
如果是临时需求,也可以把rows定义为List<List<Any>>,再手动转换元素类型,但这种方式丢失类型安全,不推荐长期使用:
data class SummaryResponse( val summary: Summary ) data class Summary( val rows: List<List<Any>> ) // 解析后手动转换类型 val response = moshi.adapter(SummaryResponse::class.java).fromJson(jsonString) response?.summary?.rows?.forEach { row -> val date = row[0] as String val itemMap = row[1] as Map<String, Any> val item = Item( name = itemMap["name"] as String, index = itemMap["index"] as Int ) val test1 = row[2] as String val test2 = row[3] as String // 处理业务逻辑 }
内容的提问来源于stack exchange,提问作者Eknath
相关产品推荐
相关产品推荐

