es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Serialización/Deserialización de Jackson por propiedad personalizada en enumeración.

Quiero hacer que Jackson funcione con enums no por nombre ni por ordinal, sino con una propiedad personalizada que agregué llamada “stringId”.
Quería admitir esto con todos los Enums en el sistema, así que creé una interfaz llamada StringIdEnum que implementará el FooEnum.

Estoy usando Kotlin, así que creé una propiedad en la interfaz llamada stringId que sobrescribo en cada valor de enum.

Ahora quiero que Jackson serialice y deserialice utilizando este campo stringId, según lo que he visto, tengo varias opciones:

  1. Usar la anotación @JsonProperty en cada valor de enum y asegurarme de que esté alineada con la propiedad stringId.
    Veo dos problemas con este enfoque. En primer lugar, es muchas anotaciones para agregar (tenemos muchas clases de enum en todo el sistema). En segundo lugar, necesito asegurarme de que el valor de la anotación y el valor de la propiedad sean siempre los mismos, lo que puede causar problemas en el futuro.

  2. Intenté usar la función READ_ENUMS_USING_TO_STRING, pero como estoy usando una interfaz, no puedo anular el método toString en la clase de interfaz (puedo anularlo en cada clase de enum, pero eso parece ser mucho código redundante).

  3. Implementar un serializador / deserializador personalizado.
    El serializador es bastante sencillo, sin embargo, tuve problemas con el deserializador.
    Quería registrar el deserializador en la interfaz StringIdEnum, pero tuve problemas para obtener todos los valores de enum en tiempo de ejecución para el enum FooType real.

StringIdEnum:

interface StringIdEnum {
   val stringId: String
}
enum class FooType(override val stringId: String) : StringIdEnum {
   FOO("FOO"),
   GOO("GOO");
}
Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para hacer que Jackson funcione con enumerados utilizando una propiedad personalizada stringId, puedes implementar un serializador/deserializador personalizado. Aquí están los pasos que puedes seguir:

    1. Crea un serializador personalizado para tu enumerado FooType que utilice la propiedad stringId:
      class FooTypeSerializer : JsonSerializer<footype>() {
          override fun serialize(
              value: FooType?,
              gen: JsonGenerator?,
              serializers: SerializerProvider?
          ) {
              gen!!.writeString(value?.stringId)
          }
      }
      
    2. Crea un deserializador personalizado para tu enumerado FooType que utilice la propiedad stringId para deserializar:
      class FooTypeDeserializer : JsonDeserializer<footype>() {
          override fun deserialize(jsonParser: JsonParser?, ctxt: DeserializationContext?): FooType {
              val node: JsonNode? = jsonParser?.codec?.readTree(jsonParser)
              val stringId = node?.get("stringId")?.asText()
              return FooType.values().first { it.stringId == stringId }
          }
      }
      
    3. Registra el serializador y deserializador con tu instancia de ObjectMapper:
      val objectMapper = ObjectMapper().apply {
          registerModule(KotlinModule())
          registerModule(SimpleModule().apply {
              addSerializer(FooType::class.java, FooTypeSerializer())
              addDeserializer(FooType::class.java, FooTypeDeserializer())
          })
      }
      

    Con estos pasos, Jackson utilizará la propiedad stringId para serializar y deserializar tu enumerado FooType. Además, puedes extender la interfaz StringIdEnum a otros enumerados que utilicen una propiedad stringId. Esto proporciona una solución limpia y reusable para manejar enumerados con propiedades personalizadas.

Comments are closed.