【问题标题】:Moshi JSON converter data exception errorMoshi JSON 转换器数据异常错误
【发布时间】:2021-09-19 14:48:11
【问题描述】:

来自服务器的模型响应:

[
  {
    "at1": true,
    "at2": "2021-07-09T08:05:54.307Z",
    "at3": "ANDROID",
  }
]

实际回复:[] 错误:com.squareup.moshi.JsonDataException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at path $

interface SomeInterface {
    fun getData(): Single<List<CustomObj>>
}

@Parcelize
data class CustomObj(
    val at1: Boolean,
    val at2: Date,
    val at3: String
) : Parcelable

我尝试使用@JsonClass(generateAdapter = true),但没有帮助。

映射:

fun toEntities(items: List<ServerResponse>?): List<CustomObj> {
    return items?.mapNotNull { toEntity(it) } ?: listOf()
}

private fun toEntity(item: ServerResponse): CustomObj? {
    return CustomObj(
        at1 = item.smth1 ?: return null,
        at2 = item.smth2 ?: return null,
        at3 = item.smth3 ?: return null
    )
}

【问题讨论】:

  • 你能发布你的代码吗?我的意思是将响应转换为Java模型的代码
  • @KhalidTaha 添加了映射部分
  • 根据我的经验,它应该是 Serializable 而不是 Parcelable,请使用 Gson 尝试以下代码:List&lt;CustomObj&gt; list = new Gson().fromJson(yourJsonResponse, new TypeToken&lt;List&lt;CustomObj&gt;&gt;(){}.getType()); 如果这有效,那么它是如何将响应转换为 java 模型的方式的问题。
  • 明确一点,您的服务器只返回一个对象列表,对吧?它不像 { "fields":[ ] } 对吧?
  • @KhalidTaha Parcelize 非常适合这个问题。如果服务器响应正确映射,即使自动生成适配器也能很好地工作

标签: android moshi


【解决方案1】:

我能够重现该错误,并在这里修复它: 使用自定义适配器:

@JsonClass(generateAdapter = true)
data class CustomObj(
    val at1: Boolean,
    val at2: Date,
    val at3: String
)

@JsonClass(generateAdapter = true)
data class CustomObjJson(
    var at1: Boolean? = null,
    var at2: String? = null,
    var at3: String? = null,
)

class CustomObjAdapter {
    @ToJson
    fun toJson(obj: CustomObj): String {
        return obj.at1.toString() + obj.at2.time.toString() + obj.at3
    }

    @FromJson
    fun fromJson(customObjJson: CustomObjJson): CustomObj {
        var at1 = customObjJson.at1 ?: false
        // TODO: find a way to convert customObjJson.at2 of type String to Date here
        var at2 = Date()
        var at3 = customObjJson.at3
        return CustomObj(at1 = at1, at2 = at2, at3 = at3 ?: "")
    }
}

如果要转换 JSON 数组,请使用类型适配器,如文档所述:Moshi Arrays

var type = Types.newParameterizedType(MutableList::class.java, CustomObj::class.java)
var moshi = Moshi.Builder().add(CustomObjAdapter()).build()
var jsonAdapter: JsonAdapter<List<CustomObj>> = moshi.adapter(type)

现在你是摇滚乐!!

    val gotcha: List<CustomObj> ? = jsonAdapter.fromJson(JSON_FROM_SERVER) as List<CustomObj>
    println(gotcha)

注意: 在您的 gradle 文件中添加以下内容:

// at top of file
plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id "org.jetbrains.kotlin.kapt"
}

// dependencies section
implementation "com.squareup.moshi:moshi:1.12.0"
kapt 'com.squareup.moshi:moshi-kotlin-codegen:1.12.0'

别忘了清理构建!干杯伙伴!

【讨论】:

    【解决方案2】:

    首先你的json 不是一个有效的json 最后不应该有任何,。 应该是这样的

    [
      {
        "at1": true,
        "at2": "2021-07-09T08:05:54.307Z",
        "at3": "ANDROID"
      }
    ] 
    
    

    要为上述创建一个 moshi 适配器,您需要创建一个单独的类型来告诉 moshi 您的 json 是以数组开始的。要处理date 属性,您需要在moshi.builder 中添加单独的适配器。您可以使用 moshi 适配器库附带的现有 Rfc3339DateJsonAdapter 适配器之一。 DateAdapterUsage

    作为这个答案的一部分,我将把日期假设为一个字符串。

    
    // Assuming Date as string
    @JsonClass(generateAdapter = true)
    data class CustomObj(
        val at1: Boolean,
        val at2: String,
        val at3: String
    )
    
    
    class Sample {
    
        private val type = Types.newParameterizedType(List::class.java, CustomObj::class.java)
        private val moshiAdapter: JsonAdapter<List<CustomObj>> = Moshi.Builder().build().adapter(type)
    
        @Test
        fun `test serialization`() {
            val sampleData =  moshiAdapter.fromJson(yourJsonString) as List<CustomObj>
    
            println(sampleData)
        }
    }
    
    

    【讨论】:

      猜你喜欢
      • 2020-04-27
      • 2020-10-31
      • 2020-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-11
      相关资源
      最近更新 更多