web-dev-qa-db-fra.com

Jackson: Sérialiser et désérialiser les valeurs enum sous forme d'entiers

Considérez l'énumération et la classe suivantes:

public enum State {
    ON,
    OFF,
    UNKNOWN
}

public class Machine {
    String name;
    int numCores;
    State state;

    public Machine(String name, int numCores, State state) {
        this.name = name;
        this.numCores = numCores;
        this.state = state;
    }
}

Et considérons la fonction principale suivante:

public static void main(String args[]) {
    Machine m = new Machine("Machine 1", 8, OFF);
    ObjectMapper mapper = new ObjectMapper();
    String machineAsJsonString = mapper.writeValueAsString(m);
    System.out.println(machineAsJsonString);
}

Actuellement, le résultat de ce principal est:

{"name" : "Machine 1", "numCores" : 8, "state" : "OFF"}

Cette sortie n'est pas bonne pour moi, car au lieu de la chaîne "OFF" pour state, j'aimerais qu'elle soit 1, qui est la valeur ordinale de OFF dans l'enum State

Donc, le résultat réel que je veux obtenir est:

{"name" : "Machine 1", "numCores" : 8, "state" : 1}

Y a-t-il une manière élégante de le faire se comporter de cette façon?

15
SomethingSomething

Cela devrait fonctionner en spécifiant JsonValue mapper. 

public enum State {
    ON,
    OFF,
    UNKNOWN;

    @JsonValue
    public int toValue() {
        return ordinal();
    }
}  

Cela fonctionne également pour la désérialisation, comme indiqué dans la Javadoc de l'annotation @JsonValue:

REMARQUE: lors de l'utilisation d'énumérations Java, une caractéristique supplémentaire est cette valeur renvoyé par la méthode annotée est également considéré comme la valeur de désérialiser à partir de, pas seulement JSON String pour sérialiser en tant que. C'est possible puisque l'ensemble des valeurs Enum est constant et qu'il est possible de définir le mappage, mais ne peut pas être fait en général pour les types POJO; comme tel n'est pas utilisé pour la désérialisation de POJO

31
user861594

Vous pouvez utiliser le réglage 

objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_INDEX);

Voir https://github.com/FasterXML/jackson-databind/blob/master/src/test/Java/com/fasterxml/jackson/databind/ser/TestEnumSerialization.Java pour des tests élémentaires

Merci de laisser un pourboire à https://righele.it/2016/01/30/jackson-deserialization-from-json-to-Java-enums/

9
Martin

Pour terminer, je poste une autre manière: sérialiseur personnalisé:

public class StateSerializer extends JsonSerializer<State> {  
    public void serialize(State value, JsonGenerator generator, SerializerProvider provider) throws IOException, JsonProcessingException {
        generator.writeStartObject();
        generator.writeFieldName("id");
        generator.writeNumber(value.getId());
        generator.writeEndObject();
    }
}

@JsonSerialize(using = StateSerializer.class)
public enum State { 
    ...
    public int getId(){...}
}
1
Paco Abato

Encore une autre manière: 

public enum State {

    @JsonProperty("0")
    ON,

    @JsonProperty("1")
    OFF,

    @JsonProperty("2")
    UNKNOWN
}

Cependant, cela produira {"state" : "1"} au lieu de {"state" : 1} (chaîne, pas numérique). Dans la plupart des cas, ça va

0
Nikolay Shevchenko