使用GSON和Retrofit解析API响应时所有属性值均为null
问题:Retrofit解析JSON后实体类属性全为null
我的App实体类
class App( var id: Int, var name: String, var description: String, var url: String, var packageName: String, var appVersion: String, var iconMediaUUID: String?, var created: String, var createdBy: String ) : Serializable
补充说明
我也尝试过使用@SerializedName注解,但没有效果。
Retrofit API调用
@GET("/api/app-list") suspend fun getApplications(): Response<List<App>>
API返回的JSON数据
[ { "id": 1, "name": "facebook", "description": "face book", "url": "https://play.google.com/store/apps/details?id=com.facebook.katana", "packageName": "com.facebook.katana", "appVersion": "1", "iconMediaUUID": null, "created": "2023-09-05 09:20", "createdBy": "ava@mail.hu" }, { "id": 3, "name": "twitter", "description": "X", "url": "https://play.google.com/store/apps/details?id=com.twitter.android", "packageName": "com.twitter.android", "appVersion": "43", "iconMediaUUID": "e2913bc1-4963-4a3e-85bf-8244b5b42979", "created": "2023-09-05 10:11", "createdBy": "ava@mail.hu" } ]
Retrofit实例
private fun getBackendClient(): Retrofit = Retrofit.Builder() .client(okHttpClient) .baseUrl(BACKEND_BASE_URL) .addConverterFactory(ScalarsConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .build() fun callBackend(): Endpoints { return getBackendClient().create(Endpoints::class.java) }
日志打印代码
val response: Response<List<App>> = API.callBackend().getApplications() if (response.isSuccessful) { val appList = response.body() if (appList != null) { Log.i("PARSED_", "size of list: "+appList.size) for (app in appList) { Log.i("PARSED_", "id: " + app.id + ", name: " + app.name) } } }
日志输出
PARSED_ size of list: 2 PARSED_ id: null, name: null PARSED_ id: null, name: null
核心问题
解析得到的实体实例所有属性值均为null,为什么无法正常解析?
解决方案
1. 将实体类改为data class或添加无参构造函数
Gson默认需要类具备无参构造函数才能完成反射赋值,Kotlin普通类默认没有无参构造,而data class会自动生成适配Gson的构造逻辑:
data class App( var id: Int, var name: String, var description: String, var url: String, var packageName: String, var appVersion: String, var iconMediaUUID: String?, var created: String, var createdBy: String ) : Serializable
如果不想用data class,可以手动添加无参构造并给属性设默认值:
class App : Serializable { var id: Int = 0 var name: String = "" var description: String = "" var url: String = "" var packageName: String = "" var appVersion: String = "" var iconMediaUUID: String? = null var created: String = "" var createdBy: String = "" constructor() constructor( id: Int, name: String, description: String, url: String, packageName: String, appVersion: String, iconMediaUUID: String?, created: String, createdBy: String ) { this.id = id this.name = name // 其他属性赋值 } }
2. 调整ConverterFactory的顺序
你当前先添加了ScalarsConverterFactory,它会优先处理文本类型数据,导致Gson转换器没机会解析JSON数组。把GsonConverterFactory放在前面:
private fun getBackendClient(): Retrofit = Retrofit.Builder() .client(okHttpClient) .baseUrl(BACKEND_BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .addConverterFactory(ScalarsConverterFactory.create()) .build()
3. 确保Gson支持Kotlin类型
如果前两步无效,检查是否添加了gson-kotlin依赖,让Gson能正确识别Kotlin属性:
implementation 'com.google.code.gson:gson:2.10.1' implementation 'com.google.gson:gson-kotlin:2.10.1'
或者手动创建带Kotlin适配器的Gson实例:
val gson = GsonBuilder() .registerTypeAdapterFactory(KotlinAdapterFactory()) .create() // 替换Retrofit中的GsonConverterFactory .addConverterFactory(GsonConverterFactory.create(gson))
内容的提问来源于stack exchange,提问作者Adam Varhegyi
相关产品推荐
相关产品推荐

