2014-10-11 2 views
0

У меня есть JSON, который является чем-то вроде следующего:преобразования JSON в объект Java дает неправильный тип перечисления

 

    [{"type":"chair", "color":"red", "owners":["A","B"]}, 
    {"type":"vase", "shape":"oval", "owners":["B", "C"]}] 

Как видно, обе записи различны. Поэтому мне нужно десериализовать этот json и создать два объекта Chair and Vase. Владельцы, указанные выше, должны быть перечислены в соответствующем объекте. У json может быть много других подобных записей и в любом порядке. Поэтому я делаю это:

List<Map<String, Object>> things = objectMapper.readValue(json, 
objectMapper.getTypeFactory().constructCollectionType(List.class, Map.class)); 

все это список карт, и каждая карта будет соответствовать одной вещи. Я перебираю список и каждую карту проверяю «тип» и создаю экземпляр соответствующего объекта. Например:

if map.get("type") == "chair" then new Chair(map.get("color"), map.get("owners")); 

Теперь у меня есть перечислений ХОЗЯЕВ. Поэтому я делаю это:

List<OWNERS> owners = (ArrayList<OWNERS>) map.get("owners"); 

Я правильно понял список. Но когда я проверяю так:

assertEquals(OWNERS.A, owners.get(0)); 

Я получаю сообщение об ошибке: 'ожидаемые java.lang.OWNERS ("А"), но получил java.lang.String ("А")'

Как вы можете вид владельцев - List. Что мне не хватает? Я разбираю неправильный путь?

+0

Какой JSON API вы используете? Проверьте класс с методом constructCollectionType, если есть способ сопоставить строки с перечислениями. Enum - это концепция Java, а не JSON. –

ответ

0

Попробуйте

assertEquals(OWNERS.A.toString(), owners.get(0)); 

Кроме того, эта линия

List<OWNERS> owners = (ArrayList<OWNERS>) map.get("owners"); 

во время выполнения работ из-за типа стирания. Он потерпит крах, если вы попытаетесь прочитать элемент списка и передать его OWNERS (потому что это будет список строк на самом деле).

Проверить Java generics - type erasure - when and what happens

0

Проблема возникает из Map<String, Object>. Ваш объект mapper не может вывести тип владельцев, он принимает предположение и предполагает, что это String.

Одна вещь, которую вы можете сделать, - это преобразовать список строк в список владельцев.

Лучшим решением было бы использовать что-то вроде jackson-databind и аннотировать ваши стулья и классы вазы. У Джексона есть аннотации, которые позволяют ему выводить тип объекта из поля JSON (например, ваше поле типа).

Ваш код должен выглядеть следующим образом:

@JsonTypeName("chair") 
@JsonTypeInfo(use=Id.NAME, include=As.PROPERTY, property="type") 
public class Chair { 
    @JsonCreator 
    public Chair(@JsonProperty("color") String color, 
       @JsonProperty("owners") List<OWNERS> owners) { } 
} 

JsonTypeInfo В аннотации сказать Джексону использовать имя вашего выбора в типе JSON свойство indentify свой класс. Аннотация JsonTypeName указывает имя вашего класса.

Если вы не хотите беспокоиться об аннотациях, вы можете использовать jackson's tree model. Чтобы загрузить ваш json-контент через интерфейс, подобный карте.

0

Использование аннотаций Джексона не было для меня. Поэтому я работал со значением по умолчанию, которое он считает i.e String.Я сделал это:

Список владельцев = (ArrayList) map.get ("owner");

И теперь конвертируется это мое перечисление путем принятия соответствующего ENUM valueOf, что строка:

OWNERS.valueOf (owners.get (0));

Смежные вопросы