Skip to content

@JsonDeserialize on Map with contentUsing custom deserializer overwrites default behavior #735

@joerglaumann

Description

@joerglaumann

I recently updated from version 2.3.3 to 2.5.1 and encountered a new issue with our custom deserializers. They either seemed to stop working or were active on the wrong fields.
I could narrow it down to some change in version 2.4.4 (2.4.3 is still working for me)

I wrote a test to show this behavior. It seems to appear when there a two maps with the same key and value types in a bean, and only one of them has a custom deserializer. The deserializer is then falsely used either for both or none of the maps.

This test works for me in version 2.4.3 and fails with higher versions.

import static org.junit.Assert.assertEquals;

import java.io.IOException;
import java.util.Map;

import org.junit.Test;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;

public class DeserializeTest {

    @Test
    public void testIt() throws Exception {
        ObjectMapper om = new ObjectMapper();
        String json = "{\"map1\":{\"a\":1},\"map2\":{\"a\":1}}";
        TestBean bean = om.readValue(json.getBytes(), TestBean.class);

        assertEquals(100, bean.getMap1().get("a").intValue());
        assertEquals(1, bean.getMap2().get("a").intValue());
    }

    public static class TestBean {

        @JsonProperty("map1")
        @JsonDeserialize(contentUsing = CustomDeserializer.class)
        Map<String, Integer> map1;

        @JsonProperty("map2")
        Map<String, Integer> map2;

        public Map<String, Integer> getMap1() {
            return map1;
        }

        public void setMap1(Map<String, Integer> map1) {
            this.map1 = map1;
        }

        public Map<String, Integer> getMap2() {
            return map2;
        }

        public void setMap2(Map<String, Integer> map2) {
            this.map2 = map2;
        }
    }

    public static class CustomDeserializer extends StdDeserializer<Integer> {

        public CustomDeserializer() {
            super(Integer.class);
        }

        @Override
        public Integer deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
            Integer value = p.readValueAs(Integer.class);
            return value * 100;
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions