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

如何用Univocity CSV Parser解析CSV并封装多字段为POJO单属性?

使用Univocity CSV Parser实现动态列映射与剩余列JSON封装

完全可以实现这个需求,核心是通过自定义RowProcessor来灵活处理每一行数据,结合Jackson将剩余列转为JSON对象。以下是具体实现步骤和代码示例:

1. 定义目标POJO

首先创建需要映射的POJO类,其中propertyC可以用Jackson的JsonNode或者Map<String, String>来存储剩余列的JSON数据:

import com.fasterxml.jackson.databind.JsonNode;

public class TargetPojo {
    private String propertyA;
    private String propertyB;
    private JsonNode propertyC;

    // 构造器、Getter和Setter方法
    public TargetPojo(String propertyA, String propertyB, JsonNode propertyC) {
        this.propertyA = propertyA;
        this.propertyB = propertyB;
        this.propertyC = propertyC;
    }

    // 省略Getter、Setter
}

2. 创建自定义RowProcessor

自定义处理器需要接收选中列的配置(比如列名),在处理每一行时完成列提取和剩余列的JSON转换:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.univocity.parsers.common.processor.RowProcessor;
import com.univocity.parsers.csv.CsvParser;
import com.univocity.parsers.csv.CsvParserSettings;

import java.util.*;

public class DynamicColumnProcessor implements RowProcessor {
    private final String columnA;
    private final String columnB;
    private final ObjectMapper objectMapper;
    private List<String> headers;
    private final List<TargetPojo> resultList = new ArrayList<>();

    public DynamicColumnProcessor(String columnA, String columnB) {
        this.columnA = columnA;
        this.columnB = columnB;
        this.objectMapper = new ObjectMapper();
    }

    @Override
    public void processStarted(CsvParser parser) {
        // 获取CSV的表头信息
        this.headers = Arrays.asList(parser.getContext().headers());
    }

    @Override
    public void processRow(String[] row) {
        Map<String, String> remainingColumns = new HashMap<>();
        String propA = null;
        String propB = null;

        for (int i = 0; i < headers.size(); i++) {
            String header = headers.get(i);
            String value = row[i];

            if (header.equals(columnA)) {
                propA = value;
            } else if (header.equals(columnB)) {
                propB = value;
            } else {
                remainingColumns.put(header, value);
            }
        }

        // 将剩余列转为JsonNode
        try {
            JsonNode jsonNode = objectMapper.valueToTree(remainingColumns);
            resultList.add(new TargetPojo(propA, propB, jsonNode));
        } catch (Exception e) {
            throw new RuntimeException("转换剩余列为JSON失败", e);
        }
    }

    @Override
    public void processEnded(CsvParser parser) {
        // 解析结束后的清理操作(可选)
    }

    public List<TargetPojo> getResultList() {
        return resultList;
    }
}

3. Spring REST接口实现

编写Controller方法,接收上传的CSV文件和选中列的JSON参数,完成解析:
首先定义接收选中列信息的DTO:

public class ColumnSelection {
    private String columnA;
    private String columnB;

    // Getter和Setter
}

然后是Controller:

import com.univocity.parsers.csv.CsvParser;
import com.univocity.parsers.csv.CsvParserSettings;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.List;

@RestController
public class CsvUploadController {

    @PostMapping("/upload-csv")
    public ResponseEntity<List<TargetPojo>> uploadCsv(
            @RequestPart("file") MultipartFile file,
            @RequestPart("selection") ColumnSelection selection) throws Exception {

        // 初始化CSV解析器设置
        CsvParserSettings settings = new CsvParserSettings();
        settings.setHeaderExtractionEnabled(true); // 自动提取表头

        // 实例化自定义处理器
        DynamicColumnProcessor processor = new DynamicColumnProcessor(selection.getColumnA(), selection.getColumnB());
        settings.setProcessor(processor);

        // 解析CSV文件
        try (InputStream inputStream = file.getInputStream()) {
            CsvParser parser = new CsvParser(settings);
            parser.parse(inputStream);
        }

        return ResponseEntity.ok(processor.getResultList());
    }
}

关键说明

  • 如果用户上传的选中列信息是列索引而非列名,只需修改DynamicColumnProcessor的逻辑,直接通过索引提取propA和propB,剩余列按表头-值的方式收集即可。
  • 若不需要JsonNode,可以直接用Map<String, String>作为propertyC的类型,省去Jackson转换步骤,更轻量化。
  • 可以根据需求添加异常处理、数据校验(比如检查选中列是否存在于CSV表头中)等逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 08:38:16