Closed
Description
Describe the bug
When deserializing a jsonSubTye which contains a map with numeric values (floats) the order of the json string results in different classes constructed.
I have pasted a complete Junit5 Test which can easily be used to reproduce the issue.
Version information
Happens from 2.12.0 onwards, in 2.11.x its ok.
To Reproduce
If you have a way to reproduce this with:
package test;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
@TestInstance(Lifecycle.PER_CLASS)
public class JacksonSubTypeBehaviourTest {
private static final Logger log = LoggerFactory.getLogger(JacksonSubTypeBehaviourTest.class);
private ObjectMapper mapper;
@BeforeAll
public void before() {
mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
}
@Test
public void testDeserializeWithDifferentOrdering() throws Exception {
String ordering1 = "{\n"
+ " \"type\": \"MAP\",\n"
+ " \"map\": {\n"
+ " \"doubleValue\": 0.1\n"
+ " }\n"
+ "}";
TestMapContainer model1 = mapper.readValue(ordering1, TestMapContainer.class);
log.info("clazz: {}", model1.getMap().get("doubleValue").getClass());
Assertions.assertTrue(model1.getMap().get("doubleValue") instanceof Double);
String ordering2 = "{\n"
+ " \"map\": {\n"
+ " \"doubleValue\": 0.1\n"
+ " },\n"
+ " \"type\": \"MAP\"\n"
+ " \n"
+ "}";
TestMapContainer model2 = mapper.readValue(ordering2, TestMapContainer.class);
log.info("clazz: {}", model2.getMap().get("doubleValue").getClass());
Assertions.assertTrue(model2.getMap().get("doubleValue") instanceof Double);
}
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
@JsonSubTypes({
@Type(value = TestMapContainer.class, name = "MAP"),
})
private static interface TestJsonTypeInfoInterface {
}
private static class TestMapContainer implements TestJsonTypeInfoInterface {
private Map<String, ? extends Object> map = new HashMap<>();
public Map<String, ? extends Object> getMap() {
return map;
}
public void setMap(Map<String, ? extends Object> map) {
this.map = map;
}
}
}
Expected behavior
Numeric values (point numbers) should always be created as Double unless stated otherwise with DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS