如何用Moshi序列化Kotlin值类使其直接返回值
解决方案:自定义Moshi JsonAdapter实现Value Class的直接字符串序列化
要让你的CustomDate value class在序列化时直接输出字符串而非嵌套对象,只需给它写一个自定义的JsonAdapter即可,具体步骤如下:
方法一:使用JsonAdapter.Factory全局注册
- 先移除
CustomDate上的@JsonClass(generateAdapter = true)注解,因为我们要自定义序列化逻辑。 - 编写一个适配器工厂类,专门处理
CustomDate的序列化与反序列化:
class CustomDateAdapterFactory : JsonAdapter.Factory { override fun create(type: Type, annotations: MutableSet<out Annotation>, moshi: Moshi): JsonAdapter<*>? { // 只处理CustomDate类型 return if (type == CustomDate::class.java) { object : JsonAdapter<CustomDate>() { // 反序列化:从字符串转成CustomDate override fun fromJson(reader: JsonReader): CustomDate? { return reader.nextString()?.let { CustomDate(it) } } // 序列化:直接写入CustomDate的value字符串 override fun toJson(writer: JsonWriter, value: CustomDate?) { value?.let { writer.value(it.value) } ?: writer.nullValue() } } } else { null } } }
- 构建Moshi实例时添加这个工厂:
val moshi = Moshi.Builder() .add(CustomDateAdapterFactory()) .build()
方法二:使用@JsonAdapter注解直接标注Value Class
如果你不想全局注册工厂,也可以直接在CustomDate上用@JsonAdapter指定适配器:
@JvmInline @JsonAdapter(CustomDateAdapter::class) value class CustomDate(val value: String) class CustomDateAdapter : JsonAdapter<CustomDate>() { override fun fromJson(reader: JsonReader): CustomDate? { return reader.nextString()?.let { CustomDate(it) } } override fun toJson(writer: JsonWriter, value: CustomDate?) { value?.let { writer.value(it.value) } ?: writer.nullValue() } }
这种方式下,构建Moshi时不需要额外添加工厂,注解会自动关联适配器。
测试验证
用你的MyTestClass测试序列化:
val testObj = MyTestClass(CustomDate("a test value")) val adapter = moshi.adapter(MyTestClass::class.java) val json = adapter.toJson(testObj) // 输出结果:{"attr1":"a test value"}
这样就能得到你期望的直接字符串形式的JSON字段了。
内容的提问来源于stack exchange,提问作者Thomas Cirksena
相关产品推荐
相关产品推荐

