使用Orika映射A到B时,Links属性触发NullPointerException求助
解决Orika映射自定义Map子类时的NullPointerException问题
我之前也碰到过Orika处理自定义Map子类时的这个坑,结合你的异常栈和代码来看,问题出在Orika默认的Map映射逻辑没法正确识别Links这个自定义HashMap子类的泛型类型,导致生成映射代码时触发NullPointerException。给你几个可行的解决办法:
方案1:显式指定links字段的自定义映射
放弃默认的byDefault()对links的自动映射,手动实现该字段的映射逻辑,绕开Orika有问题的Map自动映射:
mapper.classMap(A.class, B.class) // 手动处理links字段的映射 .fieldMap("links", "links") .customize(new CustomMapper<Links, Links>() { @Override public void mapAtoB(Links source, Links destination, MappingContext context) { if (source != null) { // 直接利用HashMap的putAll方法完成复制 destination.putAll(source); } } }) // 其他字段依然使用默认映射 .byDefault() .register();
方案2:注册全局的Links类型转换器
如果你的项目中多处需要映射Links类型,可以注册一个全局转换器,让Orika处理该类型时使用自定义逻辑:
// 注册Links到Links的转换器 mapper.getConverterFactory().registerConverter(new Converter<Links, Links>() { @Override public boolean canConvert(Type<?> sourceType, Type<?> destinationType) { return Links.class.equals(sourceType) && Links.class.equals(destinationType); } @Override public Links convert(Links source, Type<? extends Links> destinationType, MappingContext context) { if (source == null) { return null; } Links target = new Links(); target.putAll(source); return target; } }); // 之后正常注册A和B的默认映射即可 mapper.classMap(A.class, B.class) .byDefault() .register();
方案3:修改Links类的定义(可选)
如果允许修改Links类,可以尝试给它添加显式的拷贝构造方法,既简化映射逻辑,也能帮助Orika更好识别类型:
class Links extends HashMap<String, List<Link>> { // 添加拷贝构造方法 public Links(Links other) { super(other); } // 默认构造方法保留 public Links() { super(); } }
之后在自定义映射中就可以直接用拷贝构造创建实例,代码会更简洁。
问题根源补充
Orika在生成Map类型的映射代码时,会尝试反射获取泛型的类型参数,但由于Java泛型擦除,加上Links是HashMap的子类,Orika的类型解析器VariableRef在尝试判断泛型类型是否为基本类型时,因为无法正确获取到泛型参数信息而抛出空指针异常。手动指定映射逻辑可以避开这个自动解析的坑。
内容的提问来源于stack exchange,提问作者xheyhenry
相关产品推荐
相关产品推荐

