2012-01-09 12 views
17

¿es posible deserializar enumeraciones, que tienen un índice basado en uno?Jackson - deserializar una base de enumeraciones

enum Status { 
    Active, 
    Inactive 
} 

{status: 1} significa Status.Active, pero Jackson hace que sea Status.Inactive :(

+1

La pregunta no tiene nada que ver con la serialización –

+0

Como dice Oscar, la enumeración (y la informática en general) está basado en 0. Reste 1 del número si es algo que está recibiendo de otra capa. – rynmrtn

Respuesta

10

Se puede crear un deserialiser tipo personalizado para su enumeración:

public enum Status { 
    ACTIVE, 
    INACTIVE; 
    public static Status fromTypeCode(final int typeCode) { 
     switch(typeCode) { 
     case 1: return ACTIVE; 
     case 2: return INACTIVE; 
     } 
     throw new IllegalArgumentException("Invalid Status type code: " + typeCode); 
    } 
} 

public class StatusDeserializer extends JsonDeserializer<Status> { 
    @Override 
    public Status deserialize(final JsonParser parser, final DeserializationContext context) throws IOException { 
     return Status.fromTypeCode(parser.getValueAsInt()); 
    } 
} 

entonces Se puede decir Jackson a usar su deserialiser personalizado para una propiedad:

public class WarpDrive { 
    private Status status; 
    @JsonDeserialize(using = StatusDeserializer.class) 
    public void setStatus(final Status status) { 
     this.status = status; 
    } 
    public Status getStatus() { 
     return this.status; 
    } 
} 

También puede configurar el objeto de Jackson mapper para usar su deserializador personalizado para todas las ocurrencias del tipo de destino. Ver http://wiki.fasterxml.com/JacksonHowToCustomDeserializers.

3

enumeraciones tienen numéricos ordinales, a partir de cero, y se asignan a cada valor de una enumeración . en el orden en el que fueron declaradas Por ejemplo, en el código Active ha ordinal 0 y Inactive tiene ordinal 1 puede ir y venir entre el valor de una enumeración y su ordinal, como esto:.

// ordinal=0, since Active was declared first in the enum 
int ordinal = Status.Active.ordinal(); 

// enumVal=Active, since 0 is the ordinal corresponding to Active 
Status enumVal = Status.values()[0]; 

Claramente el ordinal 1 corresponde a Inactive (no es un problema de Jackson), como se explicó anteriormente, los ordinales en una enumeración son de base cero. Tal vez deberías corregir tu código para reflejar eso y asegurarte de que {status:0} significa Status.Active.

+1

Está claro, que 0 significa Status.Active en el mundo java! Pero no es mi api, solo estoy implementando un cliente. Y la API dice que 1 significa Activo y 2 Inactivo. Entonces mi pregunta era si puedo hacer que Jackson sepa sobre esto. Tal vez simplemente agregando un valor ficticio para cambiar el ordinal por uno. – Dirk

+2

No se recomienda utilizar los ordinales Enum, y mucho menos usarlos en la serialización, ya que los cambios en la definición de Enum pueden cambiar los números ordinales. – florian

44
public enum Status { 
ACTIVE(1), 
INACTIVE(2); 
private final int value; 
Status(int v) { 
    value = v; 
} 
@org.codehaus.jackson.annotate.JsonValue 
public int value() { 
    return value; 
} 
@org.codehaus.jackson.annotate.JsonCreator 
public static Status fromValue(int typeCode) { 
    for (Status c: Status.values()) { 
     if (c.value==typeCode) { 
      return c; 
     } 
    } 
    throw new IllegalArgumentException("Invalid Status type code: " + typeCode);   

}} 
+2

Esto es realmente una solución más simple, más idiomática que la mía. Gracias por compartir. – Nathan

+0

Esta es también una gran manera de manejar un problema común de enumeraciones serializadas con capitalización desconocida. –

+0

pero si enum es un tercero? – gstackoverflow

Cuestiones relacionadas