一、背景
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);
现在可以成功转换了。
参考: