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

如何无需手动设置字段,利用多对象字段创建新List

问题描述

现有两个无法修改的Java类FhExtraImportResults和FhExtra,需要将List<FhExtraImportResults>转换为包含FhExtra的所有字段,以及FhExtraImportResults中除record外其他字段的新列表。目前通过手动逐个设置字段的方式实现,希望找到更高效的替代方案。

相关类定义

public class FhExtraImportResults {
    FhExtra record;
    String error;
    Long loanId;
}

@Data
public class FhExtra {
    String LoanNumber;
    String FILoanNumber;
}

期望输出结构示例

[{
 "LoanNumber": "123",
 "FILoanNumber": "321",
 "error": "NA",
 "loanId": 456
}]

优化实现方案

以下几种方案可避免手动逐个赋值的繁琐,适配字段较多的场景:

1. Spring BeanUtils(快速轻量)

利用Spring的BeanUtils工具类批量复制字段,无需手动编写赋值逻辑,适合快速实现:

import org.springframework.beans.BeanUtils;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

public class Converter {
    public static List<HashMap<String, Object>> convert(List<FhExtraImportResults> inputList) {
        return inputList.stream().map(item -> {
            HashMap<String, Object> resultMap = new HashMap<>();
            // 复制FhExtraImportResults中除record外的字段
            BeanUtils.copyProperties(item, resultMap, "record");
            // 复制FhExtra的所有字段
            if (item.getRecord() != null) {
                BeanUtils.copyProperties(item.getRecord(), resultMap);
            }
            // 给error字段设置默认值NA
            if (resultMap.get("error") == null) {
                resultMap.put("error", "NA");
            }
            return resultMap;
        }).collect(Collectors.toList());
    }
}

2. MapStruct(类型安全,高性能)

MapStruct是编译期生成映射代码的工具,性能优于反射类工具,且能保证类型安全,适合复杂映射场景:
首先添加Maven依赖:

<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>1.5.5.Final</version>
</dependency>
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>1.5.5.Final</version>
    <scope>provided</scope>
</dependency>

定义映射接口与目标DTO:

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;
import java.util.List;

@Mapper(componentModel = "spring")
public interface FhExtraResultMapper {
    @Mapping(source = "record.LoanNumber", target = "LoanNumber")
    @Mapping(source = "record.FILoanNumber", target = "FILoanNumber")
    @Mapping(source = "error", target = "error", qualifiedByName = "defaultNA")
    TargetDto mapToDto(FhExtraImportResults source);

    List<TargetDto> mapToList(List<FhExtraImportResults> sourceList);

    @Named("defaultNA")
    default String defaultNA(String error) {
        return error == null ? "NA" : error;
    }
}

// 自定义目标DTO
public class TargetDto {
    private String LoanNumber;
    private String FILoanNumber;
    private String error;
    private Long loanId;

    // 生成getter、setter(或使用@Data注解)
}

使用时直接注入Mapper调用:

@Autowired
private FhExtraResultMapper mapper;

public List<TargetDto> convert(List<FhExtraImportResults> input) {
    return mapper.mapToList(input);
}

3. Jackson序列化合并(适配JSON输出场景)

如果最终需要输出JSON格式,可直接用Jackson将对象转为Map后合并字段:

import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class JsonConverter {
    private static final ObjectMapper objectMapper = new ObjectMapper();

    public static List<Map<String, Object>> convert(List<FhExtraImportResults> inputList) throws Exception {
        return inputList.stream().map(item -> {
            try {
                Map<String, Object> resultMap = objectMapper.convertValue(item, Map.class);
                resultMap.remove("record");
                // 合并FhExtra的字段
                if (item.getRecord() != null) {
                    Map<String, Object> recordMap = objectMapper.convertValue(item.getRecord(), Map.class);
                    resultMap.putAll(recordMap);
                }
                // 设置error默认值
                if (resultMap.get("error") == null) {
                    resultMap.put("error", "NA");
                }
                return resultMap;
            } catch (Exception e) {
                throw new RuntimeException("转换失败", e);
            }
        }).collect(Collectors.toList());
    }
}

4. 手动反射(无第三方依赖)

如果不想引入外部库,可通过Java反射遍历字段实现复制:

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ReflectConverter {
    public static List<Map<String, Object>> convert(List<FhExtraImportResults> inputList) throws IllegalAccessException {
        List<Map<String, Object>> resultList = new ArrayList<>();
        for (FhExtraImportResults item : inputList) {
            Map<String, Object> resultMap = new HashMap<>();

            // 处理FhExtraImportResults的字段
            Field[] resultFields = FhExtraImportResults.class.getDeclaredFields();
            for (Field field : resultFields) {
                field.setAccessible(true);
                if (!"record".equals(field.getName())) {
                    Object value = field.get(item);
                    if ("error".equals(field.getName()) && value == null) {
                        resultMap.put(field.getName(), "NA");
                    } else {
                        resultMap.put(field.getName(), value);
                    }
                }
            }

            // 处理FhExtra的字段
            if (item.getRecord() != null) {
                Field[] extraFields = FhExtra.class.getDeclaredFields();
                for (Field field : extraFields) {
                    field.setAccessible(true);
                    resultMap.put(field.getName(), field.get(item.getRecord()));
                }
            }

            resultList.add(resultMap);
        }
        return resultList;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 05:11:15