| package com.fasterxml.jackson.databind.module; |
| |
| import java.util.*; |
| |
| import com.fasterxml.jackson.annotation.JsonCreator; |
| import com.fasterxml.jackson.annotation.JsonProperty; |
| import com.fasterxml.jackson.core.Version; |
| import com.fasterxml.jackson.databind.BaseMapTest; |
| import com.fasterxml.jackson.databind.ObjectMapper; |
| import com.fasterxml.jackson.databind.module.SimpleModule; |
| |
| public class TestAbstractTypes extends BaseMapTest |
| { |
| static class MyString implements CharSequence |
| { |
| protected String value; |
| |
| public MyString(String s) { value = s; } |
| |
| @Override |
| public char charAt(int index) { |
| return value.charAt(index); |
| } |
| |
| @Override |
| public int length() { |
| return value.length(); |
| } |
| |
| @Override |
| public CharSequence subSequence(int arg0, int arg1) { return this; } |
| } |
| |
| public interface Abstract { |
| public int getValue(); |
| } |
| |
| public static class AbstractImpl implements Abstract { |
| @Override |
| public int getValue() { return 3; } |
| } |
| |
| // [databind#2019]: mappings from multiple modules |
| public interface Datatype1 { |
| String getValue(); |
| } |
| |
| public interface Datatype2 { |
| String getValue(); |
| } |
| |
| static class SimpleDatatype1 implements Datatype1 { |
| |
| private final String value; |
| |
| @JsonCreator |
| public SimpleDatatype1(@JsonProperty("value") String value) { |
| this.value = value; |
| } |
| |
| @Override |
| public String getValue() { |
| return value; |
| } |
| } |
| |
| static class SimpleDatatype2 implements Datatype2 { |
| private final String value; |
| |
| @JsonCreator |
| public SimpleDatatype2(@JsonProperty("value") String value) { |
| this.value = value; |
| } |
| |
| @Override |
| public String getValue() { |
| return value; |
| } |
| } |
| |
| /* |
| /********************************************************************** |
| /* Test methods |
| /********************************************************************** |
| */ |
| |
| public void testCollectionDefaulting() throws Exception |
| { |
| ObjectMapper mapper = new ObjectMapper(); |
| SimpleModule mod = new SimpleModule("test", Version.unknownVersion()); |
| // let's ensure we get hierarchic mapping |
| mod.addAbstractTypeMapping(Collection.class, List.class); |
| mod.addAbstractTypeMapping(List.class, LinkedList.class); |
| mapper.registerModule(mod); |
| Collection<?> result = mapper.readValue("[]", Collection.class); |
| assertEquals(LinkedList.class, result.getClass()); |
| } |
| |
| public void testMapDefaultingBasic() throws Exception |
| { |
| ObjectMapper mapper = new ObjectMapper(); |
| SimpleModule mod = new SimpleModule("test", Version.unknownVersion()); |
| // default is HashMap, so: |
| mod.addAbstractTypeMapping(Map.class, TreeMap.class); |
| mapper.registerModule(mod); |
| Map<?,?> result = mapper.readValue("{}", Map.class); |
| assertEquals(TreeMap.class, result.getClass()); |
| } |
| |
| // [databind#700] |
| public void testDefaultingRecursive() throws Exception |
| { |
| ObjectMapper mapper = new ObjectMapper(); |
| SimpleModule mod = new SimpleModule("test", Version.unknownVersion()); |
| |
| // defaults: LinkedHashMap, ArrayList |
| mod.addAbstractTypeMapping(Map.class, TreeMap.class); |
| mod.addAbstractTypeMapping(List.class, LinkedList.class); |
| |
| mapper.registerModule(mod); |
| Object result; |
| |
| result = mapper.readValue("[ {} ]", Object.class); |
| assertEquals(LinkedList.class, result.getClass()); |
| Object v = ((List<?>) result).get(0); |
| assertNotNull(v); |
| assertEquals(TreeMap.class, v.getClass()); |
| |
| result = mapper.readValue("{ \"x\": [ 3 ] }", Object.class); |
| assertEquals(TreeMap.class, result.getClass()); |
| Map<?,?> map = (Map<?,?>) result; |
| assertEquals(1, map.size()); |
| v = map.get("x"); |
| assertNotNull(v); |
| assertEquals(LinkedList.class, v.getClass()); |
| assertEquals(1, ((List<?>) v).size()); |
| } |
| |
| public void testInterfaceDefaulting() throws Exception |
| { |
| ObjectMapper mapper = new ObjectMapper(); |
| SimpleModule mod = new SimpleModule("test", Version.unknownVersion()); |
| // let's ensure we get hierarchic mapping |
| mod.addAbstractTypeMapping(CharSequence.class, MyString.class); |
| mapper.registerModule(mod); |
| Object result = mapper.readValue(quote("abc"), CharSequence.class); |
| assertEquals(MyString.class, result.getClass()); |
| assertEquals("abc", ((MyString) result).value); |
| |
| // and ditto for POJOs |
| mod = new SimpleModule(); |
| mod.addAbstractTypeMapping(Abstract.class, AbstractImpl.class); |
| mapper = new ObjectMapper() |
| .registerModule(mod); |
| Abstract a = mapper.readValue("{}", Abstract.class); |
| assertNotNull(a); |
| } |
| |
| // [databind#2019]: mappings from multiple modules |
| public void testAbstractMappingsFromTwoModules() throws Exception |
| { |
| ObjectMapper mapper = newJsonMapper(); |
| SimpleModule module1 = new SimpleModule("module1"); |
| module1.addAbstractTypeMapping(Datatype1.class, SimpleDatatype1.class); |
| |
| SimpleModule module2 = new SimpleModule("module2"); |
| module2.addAbstractTypeMapping(Datatype2.class, SimpleDatatype2.class); |
| mapper.registerModules(module1, module2); |
| |
| final String JSON_EXAMPLE = "{\"value\": \"aaa\"}"; |
| Datatype1 value1 = mapper.readValue(JSON_EXAMPLE, Datatype1.class); |
| assertNotNull(value1); |
| |
| Datatype2 value2 = mapper.readValue(JSON_EXAMPLE, Datatype2.class); |
| assertNotNull(value2); |
| } |
| } |