Univocity - 如何解析 CSV 并将多个字段插入到数据库中的一列中?

问题描述 投票:0回答:1

我正在使用出色的 Univocity CSV 解析器(向作者竖起大拇指!),但我正在努力寻找解决我的问题的方法。

我们使用包含 10 个字段的 CSV。用户上传 CSV 并选择 2 列,丢弃其他 8 列。上传到 Java Spring Rest 服务,文件包含所有 10 列 + 包含所选列的 JSON 对象。 目标是让 REST 服务获取文件、解析它并生成 POJO 对象,其中:

  • 属性 A = 字段#1
  • 属性 B = 字段#2
  • 属性 C = json 对象以及所有其他剩余字段

我找不到使用库来做到这一点的方法。但也许我错过了一些东西。 有人知道 Univocity CSV 解析器库是否可以实现这一点?如何实现?

提前致谢

java spring csv parsing univocity
1个回答
0
投票

您可以结合使用 Univocity CSV Parser 和 Jackson(Java 的 JSON 库)来实现此功能。

  1. 定义一个 POJO 来表示您的 CSV 数据。我们称之为 CsvData。
public class CsvData {
    private String propertyA;
    private String propertyB;
    private Map<String, String> propertyC;

    // Getters and setters
}
  1. 实现 CsvParserService 来解析 CSV 文件并创建 CsvData 对象。
import com.univocity.parsers.csv.CsvParser;
import com.univocity.parsers.csv.CsvParserSettings;

import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class CsvParserService {

    public List<CsvData> parseCsv(InputStream inputStream, Map<String, Object> selectedColumnsMap) {
        List<CsvData> csvDataList = new ArrayList<>();

        CsvParserSettings settings = new CsvParserSettings();
        settings.detectFormatAutomatically();
        CsvParser parser = new CsvParser(settings);

        parser.beginParsing(new InputStreamReader(inputStream));
        String[] headers = parser.parseNext();

        String propertyAHeader = (String) selectedColumnsMap.get("propertyA");
        String propertyBHeader = (String) selectedColumnsMap.get("propertyB");

        int[] propertyCIndexes = new int[headers.length - 2];
        int propertyCIndex = 0;
        for (int i = 0; i < headers.length; i++) {
            if (!headers[i].equals(propertyAHeader) && !headers[i].equals(propertyBHeader)) {
                propertyCIndexes[propertyCIndex++] = i;
            }
        }

        String[] row;
        while ((row = parser.parseNext()) != null) {
            CsvData csvData = new CsvData();
            csvData.setPropertyA(row[propertyAIndex]);
            csvData.setPropertyB(row[propertyBIndex]);

            Map<String, String> propertyC = new HashMap<>();
            for (int index : propertyCIndexes) {
                propertyC.put(headers[index], row[index]);
            }
            csvData.setPropertyC(propertyC);

            csvDataList.add(csvData);
        }

        return csvDataList;
    }
}
  1. 在 Spring 控制器中,处理文件上传和解析。使用 Jackson 反序列化表示所选列的 JSON 对象。
import com.fasterxml.jackson.databind.ObjectMapper;

@RestController
public class CsvUploadController {

    @Autowired
    private CsvParserService csvParserService;

    @PostMapping("/upload")
    public ResponseEntity<List<CsvData>> uploadCsv(@RequestParam("file") MultipartFile file,
                                                   @RequestParam("selectedColumns") String selectedColumns) {
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            Map<String, Object> selectedColumnsMap = objectMapper.readValue(selectedColumns, new TypeReference<Map<String, Object>>() {});

            List<CsvData> csvDataList = csvParserService.parseCsv(file.getInputStream(), selectedColumnsMap);
            return ResponseEntity.ok(csvDataList);
        } catch (IOException e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.