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

在Moshi中处理可空值的问题及构造器异常排查

解决Moshi适配可空字段及构造器异常问题

我来帮你搞定这个问题——你遇到的JsonDataException和NoSuchMethodException都是Kotlin结合Moshi/Retrofit时的常见坑,咱们一步步来解决:

一、先搞定必填字段缺失的异常

首先要明确:在Kotlin里用Moshi,不需要加@Nullable注解,那是Java时代的用法。Moshi对Kotlin的可空类型支持是靠语言本身的?和默认值来实现的。

你需要把所有可能在JSON中缺失的字段,直接声明为可空类型(加?),并且给它设置默认值null。比如OWM的返回里,rain、snow这些字段只有在对应天气出现时才会存在,所以你的CurrentWeather类要改成这样:

@JsonClass(generateAdapter = true)
data class CurrentWeather(
    @Json(name = "coord") val coordinates: Coordinates,
    @Json(name = "weather") val condition: List<Condition>,
    @Json(name = "base") val base: String,
    @Json(name = "main") val weatherCondition: Weather,
    @Json(name = "wind") val windCondition: Wind,
    @Json(name = "clouds") val cloudCondition: Cloud,
    @Json(name = "rain") val rainCondition: Rain? = null, // 可空+默认null
    @Json(name = "snow") val snowCondition: Snow? = null, // 可空+默认null
    @Json(name = "dt") val date: Double,
    @Json(name = "sys") val sysCondition: Sys,
    @Json(name = "id") val cityId: Long,
    @Json(name = "name") val cityName: String,
    @Json(name = "cod") val status: Int
)

如果还有其他可能缺失的字段(比如某些地区的sys字段会不会有特殊情况?),也照这个逻辑处理就行。

二、解决Condition类的构造器找不到异常

你改完可空字段后遇到的NoSuchMethodException,大概率是Moshi的Kotlin代码生成没配置对,或者缓存搞鬼了。咱们按顺序排查:

1. 检查依赖配置是否正确

确保你的Module级build.gradle(或build.gradle.kts)里加了Moshi的Kotlin支持和代码生成依赖:

plugins {
    id 'org.jetbrains.kotlin.android'
    // 别忘了加Moshi的代码生成插件
    id 'com.squareup.moshi' version '1.15.0' // 用最新稳定版就行
}

dependencies {
    // Moshi核心库
    implementation 'com.squareup.moshi:moshi:1.15.0'
    // Kotlin适配库
    implementation 'com.squareup.moshi:moshi-kotlin:1.15.0'
    // 关键!代码生成器,必须加,因为你用了@JsonClass(generateAdapter = true)
    kapt 'com.squareup.moshi:moshi-kotlin-codegen:1.15.0'
}

如果是Kotlin DSL,语法稍微调整一下,比如plugins里用id("com.squareup.moshi") version "1.15.0",依赖里用kapt("com.squareup.moshi:moshi-kotlin-codegen:1.15.0")。

2. 确保Condition类的字段都有默认值

看你的Condition类,目前的字段都加了可空和默认值,这是对的,但要注意OWM的weather数组里的对象通常还有main字段,如果你没声明的话,也可能出问题。建议补全所有可能的字段并设置默认值:

@JsonClass(generateAdapter = true)
data class Condition(
    @Json(name = "id") val id: Int? = null,
    @Json(name = "main") val main: String? = null, // 补全这个字段
    @Json(name = "description") val description: String? = null,
    @Json(name = "icon") val icon: String? = null // 还有icon字段,也可能用到
)

3. 清理缓存重新构建

有时候Android Studio的缓存会搞事情,导致代码生成不完整。执行:

  • Build -> Clean Project
  • 然后Build -> Rebuild Project
    或者用命令行跑./gradlew clean build,强制重新生成所有代码。

三、最后检查Retrofit的Moshi配置

这一步很容易忘!默认的Moshi实例不支持Kotlin的可空类型和数据类默认值,你必须给Moshi加上KotlinJsonAdapterFactory,然后传给Retrofit:

// 先创建带Kotlin支持的Moshi实例
val moshi = Moshi.Builder()
    .add(KotlinJsonAdapterFactory())
    .build()

fun retrofit(url: String): Retrofit = Retrofit.Builder()
    .client(owmClient)
    .baseUrl(url)
    .addConverterFactory(MoshiConverterFactory.create(moshi)) // 用这个配置好的Moshi
    .addCallAdapterFactory(CoroutineCallAdapterFactory())
    .build()

之前你直接用MoshiConverterFactory.create(),相当于用了默认的Moshi实例,没有Kotlin支持,所以可空字段的处理会出问题。

总结一下

按这个顺序来:

  1. 给所有可能缺失的字段加?和默认值null
  2. 检查并补全Moshi的Kotlin依赖和代码生成插件
  3. 给Moshi实例添加KotlinJsonAdapterFactory
  4. 清理缓存重新构建

这样就能同时解决你遇到的两个异常了,亲测适配OWM的API完全没问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:45:10