Android Moshi自定义布尔适配器失效求助:JSON布尔值格式兼容异常
问题解答
核心原因
你遇到的问题是Moshi适配器的优先级与注册方式不匹配:
- 虽然你在Moshi全局Builder里注册了
BooleanAdapter,但同时又在字段上添加了@JsonAdapter(BooleanAdapter::class)注解 - 当使用
@JsonClass(generateAdapter = true)时,字段上的@JsonAdapter要求传入的是适配器工厂(Factory),而非直接传入适配器类。直接传适配器类会导致Moshi无法正确创建适配器实例,最终还是使用默认的布尔类型适配器,自然无法解析字符串形式的"true"。
解决方案(两种可选)
方案一:移除字段上的@JsonAdapter注解,仅保留全局注册
既然已经在Moshi全局Builder中注册了BooleanAdapter,它会自动作用于所有Boolean类型的字段,不需要再在每个字段上重复添加注解。
修改后的数据类:
@JsonClass(generateAdapter = true) data class ItemResponse( @Json(name = "mSet") val IsSet: Boolean, @Json(name = "name") val name: String, @Json(name = "isPrimary") val isPrimary: Boolean )
方案二:给BooleanAdapter添加Factory,并修改字段注解
如果你需要仅在特定字段上使用该适配器(而非全局),需要给适配器添加对应的Factory实现:
- 修改BooleanAdapter,添加内部Factory类:
class BooleanAdapter : JsonAdapter<Boolean>() { @FromJson override fun fromJson(reader: JsonReader): Boolean { return when (reader.peek()) { JsonReader.Token.BOOLEAN -> reader.nextBoolean() JsonReader.Token.STRING -> { when (val value = reader.nextString()) { "true", "True", "TRUE", "1" -> true "false", "False", "FALSE", "0" -> false else -> throw JsonDataException("Invalid boolean value: $value") } } JsonReader.Token.NUMBER -> { when (val value = reader.nextInt()) { 0 -> false 1 -> true else -> throw JsonDataException("Invalid boolean value: $value") } } else -> throw JsonDataException("Expected boolean or string or int value but was ${reader.peek()}") } } @ToJson override fun toJson(writer: JsonWriter, value: Boolean?) { writer.value(value) } companion object Factory : JsonAdapter.Factory { override fun create(type: Type, annotations: Set<Annotation>, moshi: Moshi): JsonAdapter<*>? { return if (type === Boolean::class.javaObjectType || type === Boolean::class.java) { BooleanAdapter() } else { null } } } }
- 修改数据类的字段注解,指向Factory类:
@JsonClass(generateAdapter = true) data class ItemResponse( @field:JsonAdapter(BooleanAdapter.Factory::class) @Json(name = "mSet") val IsSet: Boolean, @Json(name = "name") val name: String, @field:JsonAdapter(BooleanAdapter.Factory::class) @Json(name = "isPrimary") val isPrimary: Boolean )
验证测试
使用上述任一方案后,Moshi就能正确解析JSON中字符串形式的"true"/"false"、数字0/1以及原生布尔值true/false了。
内容的提问来源于stack exchange,提问作者Ujjwal Kumar Maharana
相关产品推荐
相关产品推荐

