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

使用Gson转换JSON为POJO时报Expected BEGIN_OBJECT异常

Gson解析JSON报Expected BEGIN_OBJECT but was STRING异常排查

问题根因

异常和你定义的POJO结构、原始接口返回的JSON格式无关,核心问题出在转换逻辑的冗余序列化步骤,导致最终传入解析的JSON结构不符合预期:

  • 你代码中使用的message.data(常见于FCM推送消息回调场景)本质是Map<String, String>类型,所有字段值都被强制存储为字符串类型:orderPlacedData字段在这个Map中不是嵌套对象,而是已经序列化为字符串的JSON片段。
  • 你额外执行Gson().toJson(message.data)做二次序列化时,Gson会将Map中所有字符串值自动添加转义符、用双引号包裹,最终生成的jsonString里orderPlacedData对应的值是被双引号包裹的字符串,而非预期的嵌套对象,和你定义的POJO字段类型不匹配,因此抛出异常。

二次序列化后实际传入解析的错误结构示例:

{
  "orderPlacedData": "{\"createdAt\":\"2022-06-22T00:34:25.833Z\",\"lastUpdated\":\"2022-06-22T00:34:25.833Z\",\"orderId\":\"62b26391e5ddd5001620cd07\",\"orderedItems\":{\"quantity\":1,\"price\":654,\"id\":\"61f4da753627fc0016dfec5a\"},\"userId\":\"6294d73a789e677d84d8e282\",\"status\":\"PENDING_CONFIRMATION\"}"
}

解决方案

你可以任选以下一种方式修复,不需要修改现有定义的Kotlin数据类:

  • 直接移除冗余的二次序列化步骤,从Map中取出对应字段的字符串值单独解析:
val data = try {
    val orderPlacedDataJson = message.data.getValue("orderPlacedData")
    val orderPlacedData = Gson().fromJson(orderPlacedDataJson, OrderPlacedData::class.java)
    OrderRecievedData(orderPlacedData)
} catch (e: Exception) {
    Log.d(TAG, "onMessageReceived: exception $e")
    null
}
  • 如果需要一次性解析整个Map的内容,可以为Gson注册自定义TypeAdapter,识别字段中存储的JSON字符串并自动反序列化为对应对象,避免二次序列化带来的转义问题。
  • 如果可以调整推送/接口下发端逻辑,尽量避免将嵌套对象序列化为字符串存储在Map结构中,不过要注意FCM的data字段原生只支持字符串类型值,无法直接传递嵌套对象结构。

注意:解析前可以先打印jsonString的实际内容,就能直观看到字段被转义为字符串的问题,快速定位类型不匹配位置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 18:45:32