You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Moshi解析嵌套列表JSON报错问题及解决方法

Moshi解析嵌套JSON列表报错:找不到ArrayList的JsonAdapter

问题详情

在使用Moshi解析包含两层嵌套列表的JSON对象时遇到阻碍,JSON结构如下:

{
    "respondent_id": "1",
    "completion_status": "completed",
    "date_modified": "2023-12-05T17:41:49Z",
    "date_start": "2023-12-05T17:41:41Z",
    "responses": [
        {
            "page_index": 0,
            "page_id": "4771",
            "question_id": "1645",
            "question_index": 0,
            "question_value": "Do you like me?",
            "answers": [
                {
                    "row_index": 0,
                    "row_id": "1",
                    "row_value": "",
                    "column_index": 10,
                    "column_id": "1",
                    "column_value": "Absolutely!"
                }
            ]
        },
        {
            "page_index": 0,
            "page_id": "4771",
            "question_id": "1614",
            "question_index": 1,
            "question_value": "What's the primary reason for your rating?",
            "answers": [
                {
                    "text_response": "Because you are cool"
                }
            ]
        },
        {
            "page_index": 0,
            "page_id": "4771",
            "question_id": "1614",
            "question_index": 2,
            "question_value": "How much do you like me?",
            "answers": [
                {
                    "row_index": 0,
                    "row_id": "1182",
                    "row_value": "More than anyone else"
                }
            ]
        }
    ]
}

对应编写的Kotlin数据类:

@JsonClass(generateAdapter = true)
data class SurveyResponse(
    @SerializedName("respondent_id") val respondentId: String,
    @SerializedName("completion_status") val completionStatus: String,
    @SerializedName("date_modified") val dateModified: String,
    @SerializedName("date_start") val dateStart: String,
    @Json(name = "responses") val responses: List<SurveyQuestion>
)

@JsonClass(generateAdapter = true)
data class SurveyQuestion(
    @SerializedName("page_index") val pageIndex: Int,
    @SerializedName("page_id") val pageId: String,
    @SerializedName("question_id") val questionId: String,
    @SerializedName("question_index") val questionIndex: Int,
    @SerializedName("question_value") val questionValue: String,
    @Json(name = "answers") val answers: List<Answer>
)

@JsonClass(generateAdapter = true)
data class Answer(
    @SerializedName("row_index") val rowIndex: Int,
    @SerializedName("row_id") val rowId: String,
    @SerializedName("row_value") val rowValue: String = "",
    @SerializedName("column_index") val columnIndex: Int,
    @SerializedName("column_id") val columnId: String,
    @SerializedName("column_value") val columnValue: String
)

尝试编写自定义适配器(不确定是否必要):

class ResponsesAdapter {
    @FromJson
    fun arrayListFromJson(list: List<SurveyQuestion>): ArrayList<SurveyQuestion> = ArrayList(list)
}

class AnswersAdapter {
    @FromJson
    fun arrayListFromJson(list: List<Answer>): ArrayList<Answer> = ArrayList(list)
}

解析代码:

val moshi: Moshi = Moshi
    .Builder()
    .add(ResponsesAdapter())
    .add(AnswersAdapter())
    .build()
val jsonAdapter: JsonAdapter<SurveyResponse> = moshi.adapter<SurveyResponse>()
val surveyResponse = jsonAdapter.fromJson(jsonString)

无论调整自定义适配器写法,始终抛出错误:

java.lang.IllegalArgumentException: No JsonAdapter for
java.util.ArrayList<java.lang.String>, you should probably use List
instead of ArrayList (Moshi only supports the collection interfaces by
default) or else register a custom JsonAdapter.

但代码中并未使用ArrayList<String>,报错原因令人困惑。

解决方法

经过调试,找到两个关键修复点:

  1. 正确配置KotlinJsonAdapterFactory
    之前尝试使用KotlinJsonAdapterFactory时配置错误,写成了.adapter<SurveyResponse::class.java>(),修正为正确调用后应用不再崩溃。需确保Moshi构建时添加该工厂:
val moshi: Moshi = Moshi
    .Builder()
    .add(KotlinJsonAdapterFactory())
    .build()
val jsonAdapter: JsonAdapter<SurveyResponse> = moshi.adapter(SurveyResponse::class.java)
  1. 统一使用Moshi的@Json注解
    将数据类中所有@SerializedName注解替换为Moshi的@Json(name = "...")注解,否则所有字段解析结果都会为null。修正后的SurveyResponse示例:
@JsonClass(generateAdapter = true)
data class SurveyResponse(
    @Json(name = "respondent_id") val respondentId: String,
    @Json(name = "completion_status") val completionStatus: String,
    @Json(name = "date_modified") val dateModified: String,
    @Json(name = "date_start") val dateStart: String,
    @Json(name = "responses") val responses: List<SurveyQuestion>
)

另外,之前编写的ResponsesAdapter和AnswersAdapter属于多余代码,Moshi默认支持List接口,无需额外适配成ArrayList,可直接移除。


内容的提问来源于stack exchange,提问作者AndroidDev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 11:54:55