You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用MapStruct将HashMap<String, Object>映射为ComponentStyleDTO?

问题分析与解决方案

你遇到的空值问题核心原因是MapStruct不知道要将整个HashMap对象传递给工具类的方法,另外还有一些用法上的不规范可能导致潜在问题,下面逐一说明并给出修正方案:

核心错误:缺少source = "."指定

你的@Mapping注解没有指定source属性,MapStruct默认会尝试从源对象(HashMap)中寻找与目标字段同名的属性(比如attribute),但HashMap并没有这个属性,因此工具类的attribute()和value()方法根本没有被调用,目标字段自然保持为空。

要让MapStruct把整个HashMap作为参数传递给工具类的方法,必须在@Mapping中添加source = "."(.代表整个源对象)。

次要问题:Spring组件模型与静态工厂冲突

你在Mapper上设置了componentModel = "spring",说明希望MapStruct生成Spring管理的Bean,但同时又定义了静态的MAPPER实例通过Mappers.getMapper()获取。这种用法是矛盾的:

  • 当使用Spring组件模型时,应该通过@Autowired注入Mapper实例,而不是静态工厂获取
  • 静态工厂获取的实例不会被Spring管理,可能导致后续依赖注入相关的问题(虽然这不是本次空值的直接原因,但需要修正)

潜在风险:空指针异常

你的工具类方法没有处理HashMap为空的情况,当传入空Map时,entrySet().stream().findFirst().get()会直接抛出NoSuchElementException,需要增加空值判断。


修正后的完整代码

1. 修正ComponentStyleMapper接口

@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = "spring", uses = ComponentStyleMapperUtil.class)
public interface ComponentStyleMapper {

    @Mappings({
        @Mapping(target = "attribute", source = ".", qualifiedBy = ComponentStyleMapperUtil.Attribute.class),
        @Mapping(target = "value", source = ".", qualifiedBy = ComponentStyleMapperUtil.Value.class)
    })
    ComponentStyleDTO hashMapToComponentStyleDTO(HashMap<String, Object> hashMap);
}

2. 修正工具类ComponentStyleMapperUtil

public class ComponentStyleMapperUtil{
    @Qualifier
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.SOURCE)
    public @interface Attribute { }

    @Qualifier
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.SOURCE)
    public @interface Value { }

    @Attribute
    public String attribute(HashMap<String, Object> in){
        if (in == null || in.isEmpty()) {
            return null;
        }
        return (String) in.entrySet().stream().findFirst().get().getKey();
    }

    @Value
    public Object value(HashMap<String, Object> in) {
        if (in == null || in.isEmpty()) {
            return null;
        }
        Object value = in.entrySet().stream().findFirst().get().getValue();
        if(value instanceof String){
            return value;
        }else if(value instanceof LinkedHashMap){
            List<ComponentStyleDTO> childs = new ArrayList<>();
            HashMap<String, Object> child = (HashMap<String, Object>) value;
            for(String key: child.keySet()){
                ComponentStyleDTO schild = new ComponentStyleDTO();
                schild.setAttribute(key);
                // 去掉强制类型转换,避免类型不匹配报错
                schild.setValue(child.get(key));
                childs.add(schild);
            }
            return childs;
        }else{
            return value;
        }
    }
}

3. 正确使用Mapper(Spring注入方式)

// 在需要使用的类中注入Mapper
@Service // 或者@Component/Controller等Spring组件类
public class YourService {

    @Autowired
    private ComponentStyleMapper componentStyleMapper;

    public void yourMethod(YourAttrType attr) {
        HashMap<String, Object> hmap = new HashMap<>();
        hmap.put(attr.getKey(), attr.getValue());
        ComponentStyleDTO componentDTO = componentStyleMapper.hashMapToComponentStyleDTO(hmap);
        // 后续逻辑
    }
}

可选:不使用Spring组件模型的方案

如果你不想依赖Spring,可以移除componentModel = "spring",保留静态MAPPER实例,同样需要添加source = ".":

@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, uses = ComponentStyleMapperUtil.class)
public interface ComponentStyleMapper {
    ComponentStyleMapper MAPPER = Mappers.getMapper(ComponentStyleMapper.class);

    @Mappings({
        @Mapping(target = "attribute", source = ".", qualifiedBy = ComponentStyleMapperUtil.Attribute.class),
        @Mapping(target = "value", source = ".", qualifiedBy = ComponentStyleMapperUtil.Value.class)
    })
    ComponentStyleDTO hashMapToComponentStyleDTO(HashMap<String, Object> hashMap);
}

使用时直接调用静态实例:

ComponentStyleDTO componentDTO = ComponentStyleMapper.MAPPER.hashMapToComponentStyleDTO(hmap);

内容的提问来源于stack exchange,提问作者davis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:53:22