-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Closed
Milestone
Description
Hi everyone!
After migration from Jackson 1.9.x to 2.x (the problem can be reproduced in 2.5.0) I've got a problem deserializing generic collections.
Here's the test that documents the behavour.
Am I doing something wrong?
package com.fasterxml.jackson.databind.test;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Test;
import org.skyscreamer.jsonassert.JSONAssert;
import java.io.IOException;
import java.util.Date;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
/**
* Deserialization of class with generic collection inside depends on how is was deserialized first time.
*/
public class JacksonPolymorphicDeSerFailTest {
private static final int TIMESTAMP = 123456;
private final MapContainer originMap =
new MapContainer(ImmutableMap.<String, Object>of("DateValue", new Date(TIMESTAMP)));
/**
* If the class was first deserialized as polymorphic field,
* deserialization will fail at complex type.
*/
@Test
public void testFactorsSerializationFail() throws IOException, JSONException {
ObjectMapper mapper = new ObjectMapper();
// incorrect
MapContainer deserMapBad = createDeSerMapContainer(originMap, mapper);
assertNotEquals(originMap, deserMapBad);
assertEquals(ImmutableList.of("java.util.Date", TIMESTAMP),
deserMapBad.getMap().get("DateValue"));
// incorrect again
assertNotEquals(originMap, mapper.readValue(mapper.writeValueAsString(originMap),
MapContainer.class));
}
/**
* If the class was first deserialized as is,
* deserialization will work correctly.
*/
@Test
public void testFactorsSerializationMagicGood() throws IOException, JSONException {
ObjectMapper mapper = new ObjectMapper();
// commenting out the following statement will fail the test
assertEquals(new MapContainer(ImmutableMap.<String, Object>of("1", 1)),
mapper.readValue(
mapper.writeValueAsString(new MapContainer(ImmutableMap.<String, Object>of("1", 1))),
MapContainer.class));
MapContainer deserMapGood = createDeSerMapContainer(originMap, mapper);
// correct
assertEquals(originMap, deserMapGood);
assertEquals(new Date(TIMESTAMP), deserMapGood.getMap().get("DateValue"));
// correct again
assertEquals(originMap, mapper.readValue(mapper.writeValueAsString(originMap), MapContainer.class));
}
private static MapContainer createDeSerMapContainer(MapContainer originMap, ObjectMapper mapper)
throws JSONException, IOException {
PolymorphicValueWrapper result = new PolymorphicValueWrapper();
result.setValue(originMap);
String json = mapper.writeValueAsString(result);
System.out.println("Original map json: " + json);
JSONAssert.assertEquals("{\"value\":{\"@class\":"
+ "\"com.fasterxml.jackson.databind.test.JacksonPolymorphicDeSerFailTest$MapContainer\","
+ "\"map\":{\"DateValue\":[\"java.util.Date\",123456]}}}",
new JSONObject(json), true);
PolymorphicValueWrapper deserializedResult = mapper.readValue(json, PolymorphicValueWrapper.class);
System.out.println("Deserialized map json: " + mapper.writeValueAsString(deserializedResult));
return (MapContainer) deserializedResult.getValue();
}
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
public static class MapContainer {
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS,
include = JsonTypeInfo.As.PROPERTY,
property = "@class")
private Map<String, Object> map;
public MapContainer() { }
public MapContainer(Map<String, Object> map) {
this.map = map;
}
public Map<String, Object> getMap() {
return map;
}
public void setMap(Map<String, Object> map) {
this.map = map;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
MapContainer that = (MapContainer) o;
if (map != null ? !map.equals(that.map) : that.map != null) {
return false;
}
return true;
}
@Override
public int hashCode() {
return map != null ? map.hashCode() : 0;
}
@Override
public String toString() {
return "MapContainer{" +
"map=" + map +
'}';
}
}
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
public static class PolymorphicValueWrapper {
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS,
include = JsonTypeInfo.As.PROPERTY,
property = "@class")
private Object value;
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
}
}
Metadata
Metadata
Assignees
Labels
No labels