一、背景
Map 对象:
Map<String, Object> map = new HashMap<>();
map.put("name", "max");
map.put("age", 18);
User 实例:
@Data
public class User {
private String name;
private Byte age;
}
转换代码:
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
MapperFacade mapper = mapperFactory.getMapperFacade();
mapper.map(map, User.class);
结果:
Error occurred: java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Byte
二、原因
首先要说明的是,Orika 默认是支持 Map 对象和一般对象之间的转换的,这里报错的原因,其实是我们在 HashMap 中放入的 age 值是 Integer 类型,而 User 类中定义的 age 字段为 Byte 类型导致的。
三、解决
遇到该问题第一个想到的就是添加 Orika 的 Custom Converters 配置,于是做如下调整。
public class IntegerToByteConverter extends CustomConverter<Integer, Byte> {
@Override
public Byte convert(Integer source, Type<? extends Byte> destinationType, MappingContext context) {
return source.byteValue();
}
}
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
mapperFactory.getConverterFactory().registerConverter(new IntegerToByteConverter());
MapperFacade mapper = mapperFactory.getMapperFacade();
mapper.map(map, User.class);
然而,依旧报相同的错误。
我的理解是,Orika 并不能识别出 HashMap 对象中 age 对应值的类型(Integer),而是直接根据 Map 定义的类型(Object)来判断和使用定义的 Converter 的,所以其实要定义的是 Object 和 Byte 之间的转换器,如下。
public static class ObjectToByteConverter extends CustomConverter<Object, Byte> {
@Override
public Byte convert(Object source, Type<? extends Byte> destinationType, MappingContext context) {
if (source instanceof Integer) {
return ((Integer) source).byteValue();
}
return null;
}
}
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
mapperFactory.getConverterFactory().registerConverter(new ObjectToByteConverter());
MapperFacade mapper = mapperFactory.getMapperFacade();
mapper.map(map, User.class);
现在可以成功转换了。
参考: