如何配置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
相关产品推荐
相关产品推荐

