
本文介绍一种绕过 csv 格式缺陷的实用方案:当 csv 中某列值本身是未加引号的 json 字符串(如 {"name":"john","age":30})时,通过预处理替换边界符号并自定义引号字符,使 jackson 能安全解析嵌套 json 为字符串字段,最终输出符合预期的 json 结构。
CSV 规范明确要求:若字段值包含分隔符(如逗号)、换行符或双引号,必须用引号(默认为 ")包裹。但现实中,部分系统导出的 CSV 会直接将 JSON 字符串作为纯文本写入某列,且未加引号——这会导致标准 CSV 解析器误判字段边界,造成解析失败或数据错位。
例如以下非法 CSV:
header1,header2,header3
value1,value2,{"name":"John","age":30,"car":null}第三列的 JSON 含逗号,却无引号包裹,CsvMapper 默认会将其截断为 {"name":"John" 和 "age":30,"car":null} 两列,破坏结构。
✅ 解决思路:临时“伪引号”预处理
由于无法修改上游生成逻辑,我们采用轻量级文本预处理 + 自定义引号字符的方式:
- 将每个 JSON 字段的最外层 { 替换为 |{,} 替换为 }|(注意:仅处理首尾大括号,避免影响 JSON 内部嵌套结构);
- 配置 CsvSchema 使用 | 作为 quote character;
- Jackson 即可将 |{...}| 识别为一个完整带引号的字段,并原样保留为字符串(而非尝试解析 JSON)。
⚠️ 注意:该方法适用于 JSON 字段不嵌套在更复杂结构中(如 CSV 行内含多个 JSON 列),且 JSON 本身不含 | 字符的场景。若存在 |,需改用更安全的分隔符(如 \u0001)或正则精准匹配首尾大括号。
示例代码(Jackson 2.15+)
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;
import java.io.File;
import java.nio.file.Files;
import java.util.stream.Collectors;
public class CsvToJsonConverter {
public static void main(String[] args) throws Exception {
File csvFile = new File("./resource/test.csv").getAbsoluteFile();
String csv = Files.readAllLines(csvFile.toPath())
.stream()
.collect(Collectors.joining(System.lineSeparator()));
// ✅ 关键预处理:仅包裹最外层 JSON 的 {},避免破坏内部结构
csv = csv.replaceFirst("(?<=,|^)\\{", "|{")
.replaceAll("}\\s*(?=,|$)", "}|");
CsvMapper csvMapper = CsvMapper.builder().build();
CsvSchema schema = CsvSchema.builder()
.setQuoteChar('|')
.setUseHeader(true)
.build();
JsonNode jsonNode = csvMapper.readerFor(JsonNode.class)
.with(schema)
.readValue(csv);
// 输出格式化 JSON(含缩进)
JsonMapper jsonMapper = JsonMapper.builder()
.enable(JsonMapper.Feature.INDENT_OUTPUT)
.build();
jsonMapper.writeValue(System.out, jsonNode);
}
}输出结果
{
"header1" : "value1",
"header2" : "value2",
"header3" : "{\"name\":\"John\",\"age\":30,\"car\":null}"
}可见 header3 的值被正确保留为转义后的 JSON 字符串,完全符合需求。
总结
- 根本原因:非法 CSV 格式导致解析歧义;
- 核心技巧:用可控符号(|)临时“标记”JSON 边界,借力 CSV 引号机制实现字段隔离;
- 适用边界:适合单层 JSON 字段、无冲突字符的场景;生产环境建议推动上游修复 CSV 导出逻辑(添加标准双引号包裹);
- 扩展建议:对复杂场景,可结合 JsonParser 手动流式解析,或使用 OpenCSV + 自定义 CellProcessor 做更精细控制。










