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

如何配置Moshi将JSON中的Object类型field2转换为String类型?

解决Moshi解析JSON对象为String类型字段的问题

问题场景

给定如下JSON结构:

{
   "field1":"someValue1",
   "field2":{
      "subfield21":"asdf",
      "subfield22":"1234"
   }
}

对应的Kotlin实体类定义为:

data class MyData(
  val field1: String, 
  val field2: String
)

使用标准Moshi配置解析时,会抛出异常:moshi Expected a string but was BEGIN_OBJECT at path——原因是JSON中field2是一个对象,但实体类里声明为String类型,Moshi默认无法完成这种类型转换。

解决方案:自定义JsonAdapter

通过编写自定义的JsonAdapter,可以实现JSON对象与字符串之间的双向转换。

1. 实现自定义Adapter

import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.JsonReader
import com.squareup.moshi.JsonWriter
import com.squareup.moshi.Moshi
import com.squareup.moshi.Types
import java.io.IOException

class ObjectToStringAdapter(private val moshi: Moshi) : JsonAdapter<String>() {
    private val mapAdapter = moshi.adapter(
        Types.newParameterizedType(Map::class.java, String::class.java, Any::class.java)
    )

    @Throws(IOException::class)
    override fun fromJson(reader: JsonReader): String? {
        // 将JSON对象解析为Map,再序列化为JSON字符串
        val objMap = mapAdapter.fromJson(reader)
        return mapAdapter.toJson(objMap)
    }

    @Throws(IOException::class)
    override fun toJson(writer: JsonWriter, value: String?) {
        if (value == null) {
            writer.nullValue()
            return
        }
        // 将JSON字符串解析为Map,再序列化为JSON对象
        val objMap = mapAdapter.fromJson(value)
        mapAdapter.toJson(writer, objMap)
    }
}

2. 注册Adapter并使用

如果要让所有符合场景的字段生效,直接将Adapter添加到Moshi构建器中:

val moshi = Moshi.Builder()
    .add(ObjectToStringAdapter())
    .build()

// 解析示例
val jsonStr = """
{
   "field1":"someValue1",
   "field2":{
      "subfield21":"asdf",
      "subfield22":"1234"
   }
}
""".trimIndent()

val myData = moshi.adapter(MyData::class.java).fromJson(jsonStr)
// myData?.field2 的值为 "{\"subfield21\":\"asdf\",\"subfield22\":\"1234\"}"

3. 字段级精准适配(可选)

如果只想让特定字段使用该转换逻辑,可以配合JsonQualifier注解:

首先定义注解:

@Retention(AnnotationRetention.RUNTIME)
@JsonQualifier
annotation class ObjectAsString

修改实体类,为目标字段添加注解:

data class MyData(
  val field1: String, 
  @ObjectAsString val field2: String
)

注册Adapter时指定注解关联:

val moshi = Moshi.Builder()
    .add(ObjectAsString::class.java, ObjectToStringAdapter())
    .build()

这样只有带@ObjectAsString注解的String字段才会触发对象转字符串的逻辑,不会影响其他字段。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 13:45:37