Android Gson解析异常之MalformedJsonException

213 阅读2分钟

1:问题概述

Android Retrofit 请求网络数据,以String(LinkedTreeMap形式返回)形式返回数据.这里是以Any接收的数据.当数据中出现url地址等包含需要转义的字符串时 str转bean的时候出现异常

2: 环境

  • retrofit 2.9.0
  • converter-gson:2.9.0
  • okhttp:4.11.0
implementation 'com.squareup.okhttp3:okhttp:4.11.0'
implementation 'com.squareup.okhttp3:logging-interceptor:4.11.0'
implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'
api "com.squareup.retrofit2:retrofit:2.9.0"
implementation "com.squareup.retrofit2:converter-gson:2.9.0"
api 'io.reactivex.rxjava3:rxandroid:3.0.2'
api "io.reactivex.rxjava3:rxjava:3.1.5"

image.png

数据:


{
"action":"sms_login","api_code":200,"token":"xxx"
"user":{"video_address_suffix":null,
"push_video_add":"rtmp:\/\/push.dev.qiandurebo.com\/qiandulive\/1258",
"push_video_add2":"rtmp:\/\/push.dev.qiandurebo.com\/qiandulive\/1258",
"anchor_rank_id":"4",
"avatar":"https:\/\/imgcdn.dev.qiandurebo.com\/static_data\/uploaddata\/avatar\/1\/1973893.png_t=1721808886&imageMogr2\/thumbnail\/x150","balance":"29861232","beibei_verify":0,"show_verify":"0","birthday":0,"age":""
,....}

}



image.png

异常:

com.google.gson.stream.MalformedJsonException: Unterminated object at line 1 column 161 path $.user.push_video_add

3:思路

  • MalformedJsonException json 格式异常
  • 核心信息 push_video_add 字段异常

参考上述信息猜测 包含url等特殊字符 直接使用 Gson().formJson()需要json类型的数据 it.toString()转为Json出了异常,所以 将it.toString() 换为 Gson().toJson(it)

当你用 Retrofit + Gson 这样写:

kotlin
复制编辑
@POST("login")
suspend fun login(@Body body: RequestBody): Any

你返回的是 Any 类型,Gson 会默认把 JSON 对象反序列化为:

JSON 类型Gson 转换类型
object {}LinkedTreeMap
array []ArrayList
stringString
numberDouble
booleanBoolean
nullnull

LinkedTreeMap.toString() 会生成一个类似这种格式的字符串:

kotlin
复制编辑
{nickname=monkey, gender=1, age=25, user={id=123, token=abc123}}

⚠️ 注意:

这不是合法的 JSON!虽然看起来像 JSON,但有以下几个关键区别:

问题项描述
❌ 键没加引号JSON 中键必须是 "key" 格式
❌ 字符串值没加引号字符串类型的值必须加 ""
✅ 数值是合法的数字/布尔是合法的,但不够明确
❌ 嵌套对象格式错误嵌套结构缺引号/格式不标准

4:方案

经过上边分析 应该是url中的特殊字符在String 中的展示和json中的展示不一样.所以我们将string先转为json再给Gson使用就没问题了

//生效
val responseResult: LoginResponse = gson.fromJson<LoginResponse>(gson.toJson(it), LoginResponse::class.java)
                
//异常             
val responseResult: LoginResponse = gson.fromJson<LoginResponse>(it.toString(), LoginResponse::class.java)