Как аннотировать перечисляемые поля для десериализации с использованием Jackson JSON - PullRequest
35 голосов
/ 15 февраля 2012

Джексон 1.6.2 Веб-сервис REST / Apache Wink

Как мне аннотировать поле enum, чтобы Джексон десериализовал его?

Внутренний класс

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

Java Bean / объект запроса

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

Документы Джексона заявляют, что он может сделать это через @JsonValue / @JsonCreator, но не дают примеров (как полезно!) Я уверен, что они просто не хотят, чтобы слишком много людей использовали их каркас, поэтому они держат этот секрет.

Кто-нибудь желает пролить (Java) бобы, как это было?

Ответы [ 5 ]

44 голосов
/ 16 февраля 2012

Если вы используете Jackson 1.9, сериализация будет выполняться следующим образом:

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; }

, поэтому вам нужно добавить метод к самому типу Enum, чтобы он был у всех значений. Не уверен, что он будет работать на подтипе.

Для @JsonCreator наличие статического фабричного метода сделает это; поэтому добавив что-то вроде:

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

Jackson 2.0 фактически будет поддерживать использование только @JsonValue для обоих, включая десериализацию.

27 голосов
/ 11 марта 2016

С Джексон 2.7.2 или новее

public enum BooleanField
{
    @JsonProperty("1")
    BOOLEAN_TRUE,
    @JsonProperty("0")
    BOOLEAN_FALSE
}
14 голосов
/ 23 декабря 2015

не комментируйте их, просто настройте свой экземпляр 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;
}

и в своем перечислении переопределите метод 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;
    }
}

Вам не нужныаннотации или нестандартные десериализаторы.

3 голосов
/ 29 октября 2015

На самом деле, согласно документам для 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. 

Так что для перечислений ваша десериализация не будет работать с использованием JsonCreator, потому что JsonValue будет использоваться как для сериализации, так и для десериализации.Один из способов сделать это для перечислений - использовать JsonSetter и JsonGetter.

0 голосов
/ 25 августа 2017

Следующее может работать, если перечисление является массивом или нет.(Только для десериализации)

package com.stack.model;

import java.util.HashMap;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

import lombok.Data;

@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonPropertyOrder({ "success", "my-enums" })
public class MyObjectJSON {

    @JsonProperty("sucess")
    private boolean success;

    @JsonProperty("my-enums")
    private MyEnum[] myEnums;


    static enum MyEnum {
        Enum1, Enum2, Enum3, Enum4, EnumN;

        private static Map<String, MyEnum> myEnumsMap = new HashMap<String, MyEnum>(5);

        static {
            myEnumsMap.put("enum1-val", Enum1);
            myEnumsMap.put("enum2-val", Enum2);
            myEnumsMap.put("enum3-val", Enum3);
            myEnumsMap.put("enum4-val", Enum4);
            myEnumsMap.put("enumn-val", EnumN);
        }

        @JsonCreator
        public static MyEnum forValue(String value) {
            return myEnumsMap.get(value.toLowerCase());
        }
    }
}

Для рассмотрения:

  1. Аннотация @Data генерирует сеттеры, геттеры, toString и т. Д.
  2. @ JsonProperty("my-enums") private MyEnum [] myEnums, это способ пометить с Джексоном поле типа Enum (работает, если это массив или нет).

  3. MyEnum - это перечисление значений для сопоставления объекта JSON. Предположим, что следующий объект:

    {"sucess": true, "my-enums": ["enum1-val","enum3-val"]}

  4. Функция forValue позволяет отображать строковые значения массива в Enum, она аннотируется @JsonCreator для указания фабрики конструкций, используемой в десериализации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...