2013-08-29 4 views
1

Мы используем Jackson 1.9.1 для сериализации и десериализации строк ответа запроса JSON на/из объектов Java. Примитивные типы Java, типы коллекций и пользовательские объекты (де) сериализуются без проблем. Однако у меня есть проблема с десериализацией строки JSON в java-перечислении. JSON строку сериализации следующим образом: типDeserialize java enum от JSON

"wt":{"wt":100.5,"unit":{"LBS":3}} 

Java для масс, как так:

public class Weight { 

    protected double weight; 
    protected Unit unit; 
} 

я говорил this, this и this на SO и придумал перечисление для весовых единиц, таких как так:

public enum Unit { 

    KG("kg"), 
    GM("gm"), 
    LBS("lbs"), 
    OZ("oz"); 

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

    @JsonValue 
    public String getValue() { return this.value; } 

    @JsonCreator 
    public static Unit create(String val) { 
     Unit[] units = Unit.values(); 
     for (Unit unit : units) { 
      if (unit.getValue().equals(val)) { 
       return unit; 
      } 
     } 
     return LBS; 
    } 
} 

проблема заключается в том, когда я когда-нибудь попробовать десериализации выше JSON я получаю эту ошибку говоря : "Непризнанные поле "LBS"(класс abcdWeight), не помеченных как игнорируемые" Исключение StackTrace, как так:

Caused by: org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "LBS" (Class a.b.c.d.Weight), not marked as ignorable 
at [Source: [email protected]; line: 1, column: 464] (through reference chain: a.b.c.d.MyRequest["blah"]->a.b.c.d.AnotherType["wt"]->a.b.c.d.Weight["LBS"]) 
    at org.codehaus.jackson.map.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:53) 
    at org.codehaus.jackson.map.deser.StdDeserializationContext.unknownFieldException(StdDeserializationContext.java:267) 
    at org.codehaus.jackson.map.deser.std.StdDeserializer.reportUnknownProperty(StdDeserializer.java:673) 
    at org.codehaus.jackson.map.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:659) 
    at org.codehaus.jackson.map.deser.BeanDeserializer.handleUnknownProperty(BeanDeserializer.java:1365) 

...

Мои вопросы: ли сериализованная JSON строка для перечисления Кажется правильным? Что еще я должен включать (или аннотировать), чтобы перечисление было правильно десериализовано?

+0

Просто угадать - выглядит как это числа ваших полей перечислений, чтобы при сериализации, KG = 1, GM = 2 и т.д. Работает ли, если вы используете эти цифры в ваших перечислений инициализаторах KG используйте то есть (1); ГМ (2); LBS (3); ОЗ (4); в определении единицы перечисления? –

ответ

6

Я предполагаю, что в блоке кода public enum Unit вы имеете в виду Unit вместо WeightMeasurementUnit.

Weight класс имеет только weight и unit, так что если вы передаете {"wt":100.5,"unit":"lbs"}, он должен работать, потому что unit только блок без значения. Таким образом, десериализатор не может разобрать {"LBS":3} как Unit. Что такое 3?

Другая проблема заключается в том, что ваше значение равно «lbs», тогда как вы передаете «LBS». Так как вам нужно стандартизировать или вам нужно использовать unit.getValue().equalsIgnoreCase(val)

+0

Я думаю, что строка в вопросе заключается в том, как она сериализовала JSON - так что не под контролем, чтобы ее изменить –

+0

Raze2Dust: Моя ошибка.Да, я имел в виду Unit вместо WeightMeasurementUnit. – chetan

+0

У меня мало контроля над тем, как JSON сериализуется. Однако я хочу убедиться, что я не делаю ничего плохого в перечислении, прежде чем я могу сказать, что JSON сериализована неправильно. Благодарю. – chetan

2

Я хотел бы предложить вам обновить вашу версию Джексона 2.7.0-RC2 (и, вероятно, также раньше), а затем настроить 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 Unit { 
    KG, 
    GM, 
    LBS, 
    OZ; 

    // UPDATE: implicitly already the default so override not needed in this case 
    @Override 
    public String toString() { 
     return name(); 
    } 
} 

Вам не нужно никаких аннотаций или пользовательских deserializers. Это будет способ сопоставления простого перечисления с json и наоборот.

Если ваше перечисление должно быть отображено из специальной строки, вам необходимо добавить поле значения и конструктор, который назначает это поле и возвращает значение в методе toString.

public enum Unit { 
    KG("kilogram"), 
    GM("gram"), 
    LBS("blah"), 
    OZ("anything"); 

    Unit(final String value) { 
     this.value = value; 
    } 

    @Override 
    public String toString() { 
     return value; 
    } 
} 
Смежные вопросы