使用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>,报错原因令人困惑。
解决方法
经过调试,找到两个关键修复点:
- 正确配置KotlinJsonAdapterFactory
之前尝试使用KotlinJsonAdapterFactory时配置错误,写成了.adapter<SurveyResponse::class.java>(),修正为正确调用后应用不再崩溃。需确保Moshi构建时添加该工厂:
val moshi: Moshi = Moshi .Builder() .add(KotlinJsonAdapterFactory()) .build() val jsonAdapter: JsonAdapter<SurveyResponse> = moshi.adapter(SurveyResponse::class.java)
- 统一使用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
相关产品推荐
相关产品推荐

