package com.fasterxml.jackson.databind.deser.merge; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import com.fasterxml.jackson.annotation.JsonMerge; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.annotation.Nulls; import com.fasterxml.jackson.databind.*; public class MapMergeTest extends BaseMapTest { static class MergedMap { @JsonMerge public Map<String,Object> values; protected MergedMap() { values = new LinkedHashMap<>(); values.put("a", "x"); } public MergedMap(String a, String b) { values = new LinkedHashMap<>(); values.put(a, b); } public MergedMap(Map<String,Object> src) { values = src; } } static class MergedIntMap { @JsonMerge public Map<Integer,Object> values; protected MergedIntMap() { values = new LinkedHashMap<>(); values.put(Integer.valueOf(13), "a"); } } /* /******************************************************** /* Test methods, Map merging /******************************************************** */ private final ObjectMapper MAPPER = newObjectMapper() // 26-Oct-2016, tatu: Make sure we'll report merge problems by default .disable(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE) ; private final ObjectMapper MAPPER_SKIP_NULLS = newObjectMapper() .setDefaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.SKIP)); ; public void testShallowMapMerging() throws Exception { final String JSON = aposToQuotes("{'values':{'c':'y','d':null}}"); MergedMap v = MAPPER.readValue(JSON, MergedMap.class); assertEquals(3, v.values.size()); assertEquals("y", v.values.get("c")); assertEquals("x", v.values.get("a")); assertNull(v.values.get("d")); // but also, skip nulls v = MAPPER_SKIP_NULLS.readValue(JSON, MergedMap.class); assertEquals(2, v.values.size()); assertEquals("y", v.values.get("c")); assertEquals("x", v.values.get("a")); } public void testShallowNonStringMerging() throws Exception { final String JSON = aposToQuotes("{'values':{'72':'b','666':null}}"); MergedIntMap v = MAPPER.readValue(JSON , MergedIntMap.class); assertEquals(3, v.values.size()); assertEquals("a", v.values.get(Integer.valueOf(13))); assertEquals("b", v.values.get(Integer.valueOf(72))); assertNull(v.values.get(Integer.valueOf(666))); v = MAPPER_SKIP_NULLS.readValue(JSON , MergedIntMap.class); assertEquals(2, v.values.size()); assertEquals("a", v.values.get(Integer.valueOf(13))); assertEquals("b", v.values.get(Integer.valueOf(72))); } @SuppressWarnings("unchecked") public void testDeeperMapMerging() throws Exception { // first, create base Map MergedMap base = new MergedMap("name", "foobar"); Map<String,Object> props = new LinkedHashMap<>(); props.put("default", "yes"); props.put("x", "abc"); Map<String,Object> innerProps = new LinkedHashMap<>(); innerProps.put("z", Integer.valueOf(13)); props.put("extra", innerProps); base.values.put("props", props); // to be update MergedMap v = MAPPER.readerForUpdating(base) .readValue(aposToQuotes("{'values':{'props':{'x':'xyz','y' : '...','extra':{ 'ab' : true}}}}")); assertEquals(2, v.values.size()); assertEquals("foobar", v.values.get("name")); assertNotNull(v.values.get("props")); props = (Map<String,Object>) v.values.get("props"); assertEquals(4, props.size()); assertEquals("yes", props.get("default")); assertEquals("xyz", props.get("x")); assertEquals("...", props.get("y")); assertNotNull(props.get("extra")); innerProps = (Map<String,Object>) props.get("extra"); assertEquals(2, innerProps.size()); assertEquals(Integer.valueOf(13), innerProps.get("z")); assertEquals(Boolean.TRUE, innerProps.get("ab")); } @SuppressWarnings("unchecked") public void testMapMergingWithArray() throws Exception { // first, create base Map MergedMap base = new MergedMap("name", "foobar"); Map<String,Object> props = new LinkedHashMap<>(); List<String> names = new ArrayList<>(); names.add("foo"); props.put("names", names); base.values.put("props", props); props.put("extra", "misc"); // to be update MergedMap v = MAPPER.readerForUpdating(base) .readValue(aposToQuotes("{'values':{'props':{'names': [ 'bar' ] }}}")); assertEquals(2, v.values.size()); assertEquals("foobar", v.values.get("name")); assertNotNull(v.values.get("props")); props = (Map<String,Object>) v.values.get("props"); assertEquals(2, props.size()); assertEquals("misc", props.get("extra")); assertNotNull(props.get("names")); names = (List<String>) props.get("names"); assertEquals(2, names.size()); assertEquals("foo", names.get(0)); assertEquals("bar", names.get(1)); } }