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

Android Kotlin Retrofit调用NestJS API响应格式异常问题咨询

Retrofit调用NestJS注册接口后,UserModelIn响应显示异常格式问题

调用注册接口后,获取到的UserModelIn响应显示为:

UserModelIn(
    usernameError="error",
    passwordError="error",
    ok=false,
)

用户提供的代码:

数据类

data class UserModelOut(
    val username: String,
    val password: String,
)

data class UserModelIn(
    val usernameError: String,
    val passwordError: String,
    val ok: Boolean,
)

接口

interface ApiInterface {

    @POST("test")
    fun sendReq(@Body requestModel: RqsModel) : Call<ResModel>

    @POST("register")
    fun register(@Body registerModelOut: UserModelOut): Call<UserModelIn>
}

服务构建与请求代码

val response = ServiceBuilder.buildService(ApiInterface::class.java)
response.register(UserModelOut("", "")).enqueue(
    object : Callback<UserModelIn> {
        override fun onResponse(
            call: Call<UserModelIn>,
            response: Response<UserModelIn>
        ) {
            usernameError.text = response.body().toString()
           // var response = response.body().toString().trim();
            //textView.text = response.message().toString()
        }

        override fun onFailure(call: Call<UserModelIn>, t: Throwable) {
           // textView.text = t.toString()
        }

    }
)

原因分析

  • 字段映射不匹配:NestJS后端通常使用下划线命名(如username_error),而你的Kotlin数据类用驼峰命名(usernameError),序列化库无法自动转换,导致字段无法正确赋值,最终显示默认占位值。
  • 序列化库配置缺失:如果使用Gson,未开启驼峰与下划线的自动转换;如果使用Moshi,未添加Kotlin适配器,导致数据类无法正确序列化/反序列化。
  • 数据类非空约束问题:UserModelIn的字段都是非空类型,但后端可能返回null值,序列化库无法处理,只能填充默认的"error"或false。
  • 后端返回类型错误:比如ok字段后端返回字符串"false"而非布尔值,导致序列化失败,触发数据类默认的toString()输出。

解决步骤

  1. 抓包确认后端返回的JSON结构:用Postman或Charles工具查看NestJS返回的原始JSON,确认字段名和类型,比如:

    {
      "username_error": "用户名不能为空",
      "password_error": "密码长度不能少于6位",
      "ok": false
    }
    
  2. 修正数据类的字段映射与空值处理:添加序列化注解匹配后端字段,并将非空字段改为可空类型:

    import com.google.gson.annotations.SerializedName
    
    data class UserModelIn(
        @SerializedName("username_error")
        val usernameError: String?,
        @SerializedName("password_error")
        val passwordError: String?,
        val ok: Boolean
    )
    
  3. 配置序列化库:

    • 若使用Gson:在Retrofit构建时配置字段命名策略:
      val gson = com.google.gson.GsonBuilder()
          .setFieldNamingPolicy(com.google.gson.FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
          .create()
      
      val retrofit = Retrofit.Builder()
          .baseUrl("你的API地址")
          .addConverterFactory(GsonConverterFactory.create(gson))
          .build()
      
    • 若使用Moshi:添加Kotlin适配器依赖,并配置转换器:
      val moshi = com.squareup.moshi.Moshi.Builder()
          .add(com.squareup.moshi.kotlin.KotlinJsonAdapterFactory())
          .build()
      
      val retrofit = Retrofit.Builder()
          .baseUrl("你的API地址")
          .addConverterFactory(MoshiConverterFactory.create(moshi))
          .build()
      
  4. 检查后端DTO定义:确保NestJS的响应DTO字段类型正确,比如:

    export class UserResponseDto {
      username_error?: string;
      password_error?: string;
      ok: boolean;
    }
    
  5. 优化响应处理逻辑:在onResponse中先判断请求是否成功,再安全处理响应体:

    override fun onResponse(call: Call<UserModelIn>, response: Response<UserModelIn>) {
        if (response.isSuccessful) {
            val userModel = response.body()
            usernameError.text = userModel?.usernameError ?: "无错误信息"
            // 处理其他字段
        } else {
            usernameError.text = "请求失败:${response.code()}"
        }
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 03:50:39