Jackson Serializaiton/Deserialization 自定义 属性 在枚举中
Jackson Serializaiton/Deserialization by custom property in enum
我想让 Jackson 使用枚举而不是按名称而不是按序号,而是使用我添加的自定义 属性 称为“stringId”。
我想通过系统中的所有枚举来支持这一点,所以我创建了一个名为 StringIdEnum
的接口,FooEnum 将实现该接口。
我正在使用 Kotlin,所以我在名为 stringId
的界面中创建了一个 属性,我在每个枚举值中覆盖了它。
现在我想使用这个 stringId 字段让 Jackson 序列化和反序列化,据我所知,我有几个选择:
- 在每个枚举值上使用
@JsonProperty
注释并确保它与 stringId 属性 对齐。
我看到这种方法有两个问题。一个是要添加很多注释(我们在整个系统中有很多枚举 classes)。二 我需要确保注释值和 属性 值应始终相同,这可能会在将来导致问题。
- 我尝试使用
READ_ENUMS_USING_TO_STRING
功能,但因为我使用的是接口,所以我无法覆盖接口中的 toString class(我可以在每个枚举中覆盖它 class 但这又像是很多冗余代码)
- 实施自定义 serializer/deserializer。
序列化器非常简单,但是,我在反序列化器方面遇到了麻烦。
我想在 StringIdEnum 接口上注册反序列化器,但是我在获取实际 FooType 枚举的所有运行时枚举值时遇到了问题。
StringIdEnum:
interface StringIdEnum {
val stringId: String
}
enum class FooType(override val stringId: String) : StringIdEnum {
FOO("FOO"),
GOO("GOO");
}
设法让它工作:
@JsonSerialize(using = StringIdEnumSerializer::class)
@JsonDeserialize(using = StringIdEnumDeserializer::class)
interface StringIdEnum: DbEnum {
val stringId: String
}
class StringIdEnumSerializer: StdSerializer<StringIdEnum>(StringIdEnum::class.java) {
override fun serialize(value: StringIdEnum, gen: JsonGenerator, provider: SerializerProvider) {
gen.writeString(value.stringId)
}
}
class StringIdEnumDeserializer : JsonDeserializer<Enum<*>>(), ContextualDeserializer {
private lateinit var type: JavaType
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): Enum<*> {
val t = p.text
val enumConstants = (type.rawClass as Class<Enum<*>>).enumConstants
return enumConstants.single { (it as StringIdEnum).stringId == t }
}
override fun createContextual(ctxt: DeserializationContext?, property: BeanProperty?): JsonDeserializer<*> {
val wrapperType: JavaType = property!!.type
val stringIdEnumDeserializer = StringIdEnumDeserializer()
stringIdEnumDeserializer.type = wrapperType
return stringIdEnumDeserializer
}
}
我想让 Jackson 使用枚举而不是按名称而不是按序号,而是使用我添加的自定义 属性 称为“stringId”。
我想通过系统中的所有枚举来支持这一点,所以我创建了一个名为 StringIdEnum
的接口,FooEnum 将实现该接口。
我正在使用 Kotlin,所以我在名为 stringId
的界面中创建了一个 属性,我在每个枚举值中覆盖了它。
现在我想使用这个 stringId 字段让 Jackson 序列化和反序列化,据我所知,我有几个选择:
- 在每个枚举值上使用
@JsonProperty
注释并确保它与 stringId 属性 对齐。 我看到这种方法有两个问题。一个是要添加很多注释(我们在整个系统中有很多枚举 classes)。二 我需要确保注释值和 属性 值应始终相同,这可能会在将来导致问题。 - 我尝试使用
READ_ENUMS_USING_TO_STRING
功能,但因为我使用的是接口,所以我无法覆盖接口中的 toString class(我可以在每个枚举中覆盖它 class 但这又像是很多冗余代码) - 实施自定义 serializer/deserializer。 序列化器非常简单,但是,我在反序列化器方面遇到了麻烦。 我想在 StringIdEnum 接口上注册反序列化器,但是我在获取实际 FooType 枚举的所有运行时枚举值时遇到了问题。
StringIdEnum:
interface StringIdEnum {
val stringId: String
}
enum class FooType(override val stringId: String) : StringIdEnum {
FOO("FOO"),
GOO("GOO");
}
设法让它工作:
@JsonSerialize(using = StringIdEnumSerializer::class)
@JsonDeserialize(using = StringIdEnumDeserializer::class)
interface StringIdEnum: DbEnum {
val stringId: String
}
class StringIdEnumSerializer: StdSerializer<StringIdEnum>(StringIdEnum::class.java) {
override fun serialize(value: StringIdEnum, gen: JsonGenerator, provider: SerializerProvider) {
gen.writeString(value.stringId)
}
}
class StringIdEnumDeserializer : JsonDeserializer<Enum<*>>(), ContextualDeserializer {
private lateinit var type: JavaType
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): Enum<*> {
val t = p.text
val enumConstants = (type.rawClass as Class<Enum<*>>).enumConstants
return enumConstants.single { (it as StringIdEnum).stringId == t }
}
override fun createContextual(ctxt: DeserializationContext?, property: BeanProperty?): JsonDeserializer<*> {
val wrapperType: JavaType = property!!.type
val stringIdEnumDeserializer = StringIdEnumDeserializer()
stringIdEnumDeserializer.type = wrapperType
return stringIdEnumDeserializer
}
}