web-dev-qa-db-fra.com

Comment annoter des champs d'énumération pour la désérialisation à l'aide de Jackson JSON

Jackson 1.6.2 REST service Web/Apache Wink

Comment annoter un champ enum pour que Jackson le désérialise?

Classe intérieure

public enum BooleanField
{
    BOOLEAN_TRUE        { public String value() { return "1";} },
    BOOLEAN_FALSE       { public String value() { return "0";} },

Objet Java Bean/Request

BooleanField locked;
public BooleanField getLocked() {return locked;}

Les documents de Jackson indiquent qu'il peut le faire via @JsonValue/@JsonCreator mais ne fournit aucun exemple (utile!). Je suis sûr qu'ils ne veulent tout simplement pas que trop de gens utilisent leur framework, ils gardent donc ce secret.

Quiconque est prêt à renverser les haricots (Java), pour ainsi dire?

36
rakehell

Si vous utilisez Jackson 1.9, la sérialisation se fera par:

public enum BooleanField {
   BOOLEAN_TRUE("1")
   ;

   // either add @JsonValue here (if you don't need getter)
   private final String value;

   private BooleanField(String value) { this.value = value; }

   // or here
   @JsonValue public String value() { return value; }

le changement dont vous avez besoin consiste à ajouter une méthode au type Enum lui-même, de sorte que toutes les valeurs l'ont. Je ne sais pas si cela fonctionnerait sur le sous-type.

Pour @JsonCreator, avoir une méthode d'usine statique le ferait; donc en ajoutant quelque chose comme:

@JsonCreator
public static BooleanField forValue(String v) { ... }

Jackson 2.0 supportera en fait l'utilisation de seulement @JsonValue pour les deux, y compris la désérialisation.

44
StaxMan

Avec Jackson 2.7.2 ou plus récent

public enum BooleanField
{
    @JsonProperty("1")
    BOOLEAN_TRUE,
    @JsonProperty("0")
    BOOLEAN_FALSE
}
32
softarn

ne les annotez pas, configurez simplement votre instance ObjectMapper:

private ObjectMapper createObjectMapper() {
    final ObjectMapper mapper = new ObjectMapper();
    // enable toString method of enums to return the value to be mapped
    mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
    mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
    return mapper;
}

et dans votre énumération, remplacez la méthode toString ():

public enum SectionType {
START("start"),
MORE("more");

    // the value which is used for matching
    // the json node value with this enum
    private final String value;

    SectionType(final String type) {
        value = type;
    }

    @Override
    public String toString() {
        return value;
    }
}

Vous n'avez pas besoin d'annotations ou de désérialiseurs personnalisés.

15
luckyhandler

En fait, selon les documents pour JsonValue (Jackson 2.3.3):

NOTE: when use for Java enums, one additional feature is
 * that value returned by annotated method is also considered to be the
 * value to deserialize from, not just JSON String to serialize as.
 * This is possible since set of Enum values is constant and it is possible
 * to define mapping, but can not be done in general for POJO types; as such,
 * this is not used for POJO deserialization. 

Ainsi, pour les énumérations, votre désérialisation ne fonctionnera pas à l'aide de JsonCreator car JsonValue sera utilisé à la fois pour la sérialisation et la désérialisation. Une façon de procéder pour les énumérations consiste à utiliser JsonSetter et JsonGetter.

3
user2706588