以下测试失败
java.util.LinkedHashMap cannot be cast to org.dabd.mapping2.MapperImplNGTest$Foo
java.lang.ClassCastException
at org.dabd.mapping2.MapperImplNGTest.testFromMap(MapperImplNGTest.java:82)
我能找到的唯一解决方案是将fromMap签名更改为T fromMap(S map, Class<T> clazz)
,但我认为没有必要明确地传递该类。 TypeReference不足以实例化类型T吗?感谢。
import java.util.Map;
public interface Mapper<T extends Object, S extends Map<String, Object>> {
public S toMap(T obj);
public T fromMap(S map);
}
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Map;
public class MapperImpl<T extends Object, S extends Map<String, Object>>
implements Mapper<T, S> {
public S toMap(T obj) {
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> map = objectMapper.convertValue(obj, Map.class);
return (S) map;
}
public T fromMap(S map) {
ObjectMapper objectMapper = new ObjectMapper();
T obj = objectMapper.convertValue(map, new TypeReference<T>() {
});
return obj;
}
}
测试
import java.util.HashMap;
import java.util.Map;
import static org.testng.Assert.*;
import org.testng.annotations.Test;
public class MapperImplNGTest {
public static class Foo {
private String a;
public String getA() {
return a;
}
public void setA(String a) {
this.a = a;
}
}
public MapperImplNGTest() {
}
@Test
public void testFromMap() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("a", "aa");
MapperImpl<Foo, Map<String, Object>> mapper = new MapperImpl<Foo, Map<String, Object>>();
Foo foo = mapper.fromMap(map);
assertEquals(foo.getA(), map.get("a"));
}
}
答案 0 :(得分:2)
不,您不能以T
方式使用TypeReference
等类型变量:您必须传递实际参数化。这是因为这里没有与T
相关的运行时信息:它只是一个占位符。所以它被有效地视为java.lang.Object
。
但您可以使用TypeFactory
以编程方式构建结构化类型(其实例可通过ObjetMapper.getTypeFactory()
获得)。您仍然需要表示键和值类型的Class
个实例,但有了这些信息,就可以构造包含您需要的完整类型信息的JavaType
值。
答案 1 :(得分:0)
你可以这样做
public T fromMap(S map, TypeReference<T> typeReference) {
ObjectMapper objectMapper = new ObjectMapper();
T obj = objectMapper.convertValue(map, typeReference);
return obj;
}