Stas
Stas

Reputation: 1725

Trivial JSON jackson polymorphic deserialization

Struggling with something which looks like trivial and should work without any problems. I have JSON with "@class" property and without knowing it's class on the moment of invocation readValue() want to deserialize it into the object of the class referenced by "@class". What I get back instead is "LinkedHashMap".

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

Sorry, if dup, but couldn't find exactly the same problem. The most of people have more complicated cases where there is base class, which is also annotated, etc. These cases actually work fine.

I'm using jackson 2.6.6

Upvotes: 0

Views: 406

Answers (2)

Stas
Stas

Reputation: 1725

Apparently adding this line makes this test work:

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

In that case annotation on the Sample class is not necessary.

Upvotes: 0

Sachin Gupta
Sachin Gupta

Reputation: 8358

Jackson converts it into LinkedhashMap, so that later, we can you use its convert method to convert given LinkedhashMap into custom Object. So here you need to add one more step into it.

E.g:

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

So you can preserve this obj somewhere, and can convert it into Sample class at your convenience.

Upvotes: 1

Related Questions