【问题标题】:How to parse retrofit json response to object model with Moshi如何使用 Moshi 解析对对象模型的改造 json 响应
【发布时间】:2020-09-26 02:09:19
【问题描述】:

改造实例:

    fun getMoshi() : Moshi{
        return Moshi.Builder()
            .add(KotlinJsonAdapterFactory())
            .build()
    }


    fun retrofit(baseUrl: String): Retrofit = Retrofit.Builder()
        .client(getClient())
        .baseUrl(baseUrl)
        .addConverterFactory(MoshiConverterFactory.create(getMoshi()).asLenient())
        .build()

}

BaseValidation 模型:

    @JsonClass(generateAdapter = true)
    data class BaseValidation (
        val status : String,
        val data : List<Data>
    )

响应解析:

   val type: Type = Types.newParameterizedType(String::class.java, Data::class.java)
    val moshi = Moshi.Builder().build()
    val jsonAdapter: JsonAdapter<Map<String,Data>> = moshi.adapter(type)
    val baseValidation = jsonAdapter.fromJson(response.errorBody()!!.charStream().toString())!!

结果:

Platform class java.lang.String in java.lang.String<com.example.vow.data_remote.model.create.response.validation.Data> requires explicit JsonAdapter to be registered

我是 Moshi 新手,有点困惑如何正确解析,我已经使用下面的代码通过 gson 实现了结果,但我想了解 Moshi 是如何完成的:

val gson = Gson()
val type = object : TypeToken<BaseValidation>() {}.type
var errorResponse: BaseValidation? = gson.fromJson(response.errorBody()!!.charStream(), type)

下面的类型定义正确吗?

val type: Type = Types.newParameterizedType(String::class.java, Data::class.java)

更新

val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
val jsonAdapter: JsonAdapter<BaseValidation> = moshi.adapter(BaseValidation::class.java).lenient()
val baseValidation = jsonAdapter.fromJson(response.errorBody()!!.charStream().toString())!!

返回

com.squareup.moshi.JsonEncodingException: Use JsonReader.setLenient(true) to accept malformed JSON at path $

当 moshi 设置为 lenient() 时

moshi.adapter(BaseValidation::class.java).lenient()

我明白了

Expected BEGIN_OBJECT but was STRING at path $

OkHttp 响应是

{
    "status": "validation",
    "data": [
        {
            "type": "Email",
            "code": 3000,
            "field": "User.contact.email",
            "message": "Email is invalid"
        }
    ]
}

解决方案

也许将来会对某人有所帮助

 response.errorBody()!!.charStream().toString()

应该是

response.errorBody()?.source()

【问题讨论】:

  • 我真的很好奇是否可以不创建一个数据类来检索状态和数据属性,而是立即访问数据数组属性。在我的情况下,状态总是成功的,所以创建一个保存状态和数据列表的数据类是没有意义的。想法?
  • 我看到你正在使用带有 KotlinJsonAdapterFactory 和 MoshiConverterFactory 的 Retrofit,但 MoshiConverterFactory 在 Retrofit converter-moshi 库中,而 KotlinJsonAdapterFactory 在 moshi-kotlin 依赖项中,当我尝试要添加它们,会出现一个警告,指出存在重复的类。你是怎么解决这个问题的?也许从改造中排除一些东西?

标签: android kotlin retrofit retrofit2 moshi


【解决方案1】:

如果您想将 Moshi 与 Kotlin 反射一起使用,请不要忘记添加 KotlinJsonAdapterFactory。我猜这会很好用:

val moshi = Moshi.Builder()
    .add(KotlinJsonAdapterFactory())
    .build()
val jsonAdapter = moshi.adapter(BaseValidation::class.java)
val baseValidation = jsonAdapter.fromJson(response.errorBody()!!.charStream().toString())!!

另外,你可以从你的类中移除 @JsonClass 注释。使用反射时不需要它。

【讨论】:

    猜你喜欢
    • 2021-03-15
    • 2021-12-09
    • 2019-05-05
    • 1970-01-01
    • 2021-02-03
    • 1970-01-01
    • 1970-01-01
    • 2017-05-12
    • 1970-01-01
    相关资源
    最近更新 更多