43 votes

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

J'utilise le service Web REST/Apache Wink avec Jackson 1.6.2. 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/Requête

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

La documentation de Jackson indique qu'il peut le faire via @JsonValue / @JsonCreator mais ne fournit aucun exemple.

Quelqu'un est-il prêt à renverser les haricots (de java), pour ainsi dire?

55voto

StaxMan Points 34626

Si vous utilisez Jackson 1.9, la sérialisation serait effectuée 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; }

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

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

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

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

51voto

softarn Points 1422

Avec Jackson 2.7.2 ou plus récent

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

23voto

Andev Points 11

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.

3voto

user2706588 Points 31

En fait, selon la documentation de 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 avec 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.

0voto

rakehell Points 188
public enum BooleanField
{
    BOOLEAN_TRUE("1"),      
    BOOLEAN_FALSE("0");
    
    private final String value;

    BooleanField( int value ) { this.value = value; }
    
}

Désérialiseur

 import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;

public class BooleanFieldDeserializer extends Json Deserializer<BooleanField> {
    
    public BooleanField deserialize( JsonParser p, DeserializationContext ctx )
    throws IOException 
    {
        // boilerplate code for every deserializer
        ObjectCodec objectCodec = p.getCodec();
        JsonNode node = objectCodec.readTree(p);

        // customizable part for your impl
        String booleanFieldString = node.asText();
        return valueOf( booleanFieldString ); <- Enum-supplied method
    }

Ensuite, dans votre JavaBean...

 @JsonDeserialize(using = BooleanFieldDeserializer.class)
BooleanField locked;

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