【问题标题】:Calling Secondary Constructor in API response Model in Kotlin Android在 Kotlin Android 的 API 响应模型中调用辅助构造函数
【发布时间】:2020-05-07 08:24:47
【问题描述】:

我的 JSON 响应看起来像-

{
    "body": {
        "count": 4,
        "sender": "margarete20181570"
    },
    "inserted_at": "2020-05-07T05:48:14.465Z",
    "type": 1
},
{
    "body": "savanna19562530 hit the SOS button!",
    "inserted_at": "2020-05-06T09:17:36.658Z",
    "type": 2
}

我正在使用下面的数据类来解析上面的 JSON,这里有什么问题!

data class Notification(val body: String, val inserted_at: String, val type: Int) {

constructor(
    msgBody: MessageNotification,
    inserted_at: String,
    type: Int
) : this(msgBody.sender + "Sent you " + msgBody.count + "Messages", inserted_at, type)

}

但是这个dosent工作它会产生解析错误 - Expected String , got object

我的 Api 调用看起来像-

@GET("notifications")
suspend fun getNotifications(
    @HeaderMap headers: HashMap<String, String>
): Response<List<Notification>>

主要目标是如何重构代码,使得Notification模型类的不同构造函数将在不同的情况下被调用,这样它就不会出现expecting string, got objectexpecting object got string这样的错误

我应该如何改进我的代码来解析响应?

感谢任何帮助!

【问题讨论】:

  • body JSON 响应中的字段是第一个对象和第二个字符串。这可能是您遇到错误的情况。
  • 是的,我知道错误,这是我的问题,即如何改造我的数据类以捕获这两种类型,这就是为什么我也引入了辅助构造函数
  • 你使用哪个库进行反序列化?
  • 我只是在手动使用改造和反序列化使用数据类

标签: android json api kotlin data-class


【解决方案1】:

由于您是手动反序列化 JSON,这可能是您可以尝试的解决方案

data class Body(val count: Int, val sender: String)

data class Notification(val body: Any, val insertedAt: String, val type: Int)

现在,解析 JSON 响应

val jsonResponse = JSONArray(/*JSON response string*/) // I am guessing this is an array

    (0 until jsonResponse.length()).forEach {
        val jsonObj = jsonResponse.getJSONObject(it)
        val jsonBody = jsonObj.get("body")
        if (jsonBody is String) {
            // Body field is a String instance
            val notification = Notification(
                body = jsonBody.toString(),
                insertedAt = jsonObj.getString("inserted_at"),
                type = jsonObj.getInt("type")
            )
            // do something
        } else {
            // Body field is a object
            val jsonBodyObj = jsonObj.getJSONObject("body")
            val body = Body(
                count = jsonBodyObj.getInt("count"),
                sender = jsonBodyObj.getString("sender")
            )
            val notification = Notification(
                body = body,
                insertedAt = jsonObj.getString("inserted_at"),
                type = jsonObj.getInt("type")
            )

            // do something
        }
    }

我希望这有助于或至少让您了解如何解决问题。也可以查看Gson排除策略。

【讨论】:

  • 实际上它非常复杂,因为我在 recycleview 中使用数据绑定并将对象分配为 override fun onBindViewHolder(holder: NotificationAdapter.NotificationViewHolder, position: Int) { holder.notificationListItemBinding.notifyItem = notificationList[position] } 这就是为什么如果我可以直接调用构造函数并检索对象会更好
  • 我已经添加了 api 调用,我不能使用那个 json 解构 @Hussain
  • 即使您使用视图绑定,也可以使用条件绑定或自定义设置器
  • 当我调用 api 并接受上述数据类的响应时,它给出了错误,所以请告诉我应该在这里输入什么 : Response&lt;List&lt;Notification&gt;&gt; 代替 Notification 类,因为它会自动尝试输入投射到给定的模型中
  • 你可以把body当作Any,在你收到响应类型转换后根据你的需要
【解决方案2】:

JSON 中的 body 字段是一个对象,应该映射到项目中定义的对象。为此,您可以使用如下的类头:

data class Body(val count: Int, val sender: String)

您的 Notification 类标头将有一个 Body 字段来捕获您的 JSON 响应的该部分,如下所示:

data class Notification(val body: Body, val inserted_at: String, val type: Int)

我通常使用 Gson 来反序列化 Retrofit 响应。它工作得很好,而且很容易定制。如果有什么需要澄清的,请告诉我。

【讨论】:

  • 我认为这与删除的答案相同
  • 我不知道有一个已删除的答案。你试过这个吗?
  • 是的,它给出错误,expecting string , got object
  • 你到底是从哪里得到这个错误的?我猜这是因为您的 JSON 响应中的第二个对象。在第一个对象中,body 是一个对象,而在第二个对象中,body 是一个字符串。如果您可以控制网络 API,我建议您多考虑一下 body 实体,以便您可以使格式保持一致。您的 body 对象似乎可以使用三个字段:countsendermessage。当然,我只是推测,你应该知道的更多。
  • 是的,我可以更改 API JSON 类型,但我只是想探索一下是否可行
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-28
  • 2017-03-12
  • 1970-01-01
相关资源
最近更新 更多