13 votes

Jackson : sérialisation et désérialisation des valeurs d'énumération sous forme d'entiers

Considérons l'enum et la classe suivants :

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érez 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, la sortie 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 de caractères "OFF" para state J'aimerais que ce 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}

Existe-t-il un moyen élégant de le faire se comporter de cette façon ?

25voto

user861594 Points 646

Cela devrait fonctionner en spécifiant JsonValue mappeur.

public enum State {
    ON,
    OFF,
    UNKNOWN;

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

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

REMARQUE : lors de l'utilisation des enums Java, une caractéristique supplémentaire est que la valeur retournée par la méthode annotée est également considérée comme la valeur à désérialiser, et pas seulement la chaîne JSON à sérialiser. Cela est possible puisque l'ensemble des valeurs d'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 Enum n'est pas utilisé pour la désérialisation des POJO.

8voto

Martin Points 149

Vous pouvez utiliser le réglage

objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_INDEX);

Ver https://github.com/FasterXML/jackson-databind/blob/master/src/test/java/com/fasterxml/jackson/databind/ser/TestEnumSerialization.java pour les cas de test complets

Merci au conseil de https://righele.it/2016/01/30/jackson-deserialization-from-json-to-java-enums/

2voto

Tom C Points 574

Si vous voulez imprimer l'ordinal de l'enum, vous pouvez modifier votre constructeur pour qu'il accepte un fichier de type int au lieu de State et ensuite dans votre appel à Machine vous pouvez le structurer de la manière suivante :

Machine m = new Machine("Machine 1", 8, State.OFF.ordinal());

Cette opération récupère la valeur ordinale de l'enum de l'état transmis et imprime ce qui suit

{name='Machine 1', numCores=8, state=1}

1voto

Paco Abato Points 2924

Pour compléter, j'affiche un autre moyen : le 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(){...}
}

0voto

Nikolay Shevchenko Points 1315

Encore une autre façon :

public enum State {

    @JsonProperty("0")
    ON,

    @JsonProperty("1")
    OFF,

    @JsonProperty("2")
    UNKNOWN
}

Cependant, cela produira {"state" : "1"} au lieu de {"state" : 1} (chaîne de caractères, non numérique). Dans la plupart des cas, c'est OK

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X