2016-09-29 5 views
0

Борьба с чем-то, что выглядит тривиально и должно работать без проблем. У меня JSON с свойством «@class» и, не зная, что это класс в момент вызова, readValue() хочет десериализовать его в объект класса, на который ссылается «@class». Вместо этого я получаю ссылку «LinkedHashMap».Trivial JSON jackson полиморфная десериализация

@Test 
public void toJsonAndBack() throws Exception { 
    ObjectMapper mapper = new ObjectMapper(); 
    String json = mapper.writeValueAsString(new Sample("id")); 
    assertTrue(json.contains("@class")); 
    Sample obj = (Sample)mapper.readValue(json, Object.class); 
} 

@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS) 
static class Sample { 
    private String id; 

    public Sample() { 
    } 

    public Sample(String id) { 
     this.id = id; 
    } 

    public String getId() { 
     return id; 
    } 
} 

Извините, если одурачить, но не удалось найти точно такую ​​же проблему. Большинство людей имеют более сложные случаи, когда есть базовый класс, который также аннотируется и т. Д. Эти случаи действительно работают нормально.

Я использую Джексон 2.6.6

+0

Не уверен, что я понимаю ваш вопрос, но правильная идиома для де-сериализации просто будет «Образец obj = mapper.readValue (json, Sample.class);', no casting. – Mena

+0

@Mena В действительности, конечно, случай немного сложнее, это просто пример, иллюстрирующий желаемое поведение. Я не могу использовать информацию о типе. – Stas

ответ

1

Джексон превращает его в LinkedhashMap, чтобы потом, мы можем использовать его метод преобразования для преобразования с учетом LinkedhashMap в пользовательский объект. Поэтому здесь вам нужно добавить еще один шаг.

например:

ObjectMapper mapper = new ObjectMapper(); 
String json = mapper.writeValueAsString(new Sample("id")); 
Object obj = mapper.readValue(json, Object.class); 
Sample sample = mapper.convertValue(obj, Sample.class); 

Таким образом, вы можете сохранить это OBJ где-нибудь, и может превратить его в Sample класс в удобное время.

+0

Thx, это работоспособно. Я могу прочитать свойство «@class» на карте, получить класс и передать его в convertValue(). Я просто надеялся оставить всю эту сантехнику для ручки Джексона. – Stas

0

Видимо, добавляя эту строку делает эту работу испытания:

mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); 

В этом случае аннотаций на классе образца не является необходимым.

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