为了账号安全,请及时绑定邮箱和手机立即绑定

为什么 Jackson 在重建配置模式以构建 CSV 记录行时将包含逗号的字符串括起来?

为什么 Jackson 在重建配置模式以构建 CSV 记录行时将包含逗号的字符串括起来?

慕森卡 2023-12-13 16:53:04
我从存储库获取数据并将其放入 CSV 中。为了建立一条记录线,我使用杰克逊。我的目标是如果该字段值包含逗号,则用双引号将该字段(字符串类型)括起来。所以输出应该是这样的:some-uuid-value,一些不带逗号的字符串,SOMETHING,123456,www.some.url 等some-uuid-value,“一些字符串,但带逗号”,SOMETHING,123456,www.some.url 等一些- uuid-value、一些不带逗号的字符串、SOMETHING、123456、www.some.url 等我想出了这个代码:private String toCsvString(EntityCsvRecord entity) {        CsvMapper mapper = new CsvMapper();        CsvSchema schema = mapper.schemaFor(EntityCsvRecord.class).withoutQuoteChar();        if (entity.getName() == null) {            entity.setName("");        }        if (entity.getName().contains(",")) {            String columnName = "name";            int nameColumnIndex = schema.column(columnName).getIndex();            schema = mapper                .configure(CsvGenerator.Feature.STRICT_CHECK_FOR_QUOTING, true)                .schemaFor(EntityCsvRecord.class)                .rebuild()                .replaceColumn(nameColumnIndex, new CsvSchema.Column(nameColumnIndex, columnName))                .build();        }        try {            return mapper.writer(schema).writeValueAsString(entity);        } catch (Exception e) {            ...        }    }但是,我不明白为什么它会这样工作,我在文档中找不到任何血统线索。有人能解开这个谜团吗?
查看完整描述

1 回答

?
ITMISS

TA贡献1871条经验 获得超8个赞

整个技巧是启用CsvGenerator.Feature.STRICT_CHECK_FOR_QUOTING功能。来自文档:

确定在确定列值需要引用之前完成多少工作的功能:当设置为 true 时,将进行全面检查以仅在绝对必要时使用引用;但当为 false 时,会进行更快但更保守的检查,并且可能对可能不需要的值使用引号。权衡基本上是在最佳/最小引用(true)和更快的处理(false)之间。更快的检查涉及仅检查值的前 N 个字符,以及可能的更宽松的检查。

但请注意,无论设置如何,所有需要引用的值都将是:只是当设置为 false 时,还可以引用其他值(以避免必须进行更昂贵的检查)。

对于“宽松”(近似、保守)检查,默认值为 false。

您可以删除模式和映射器的所有其他配置,并且它将以相同的方式工作。您可以将其简化为以下代码:

class CsvEntityGenerator {


    private final CsvMapper mapper;

    private final CsvSchema schema;


    public CsvEntityGenerator(Class clazz) {

        mapper = new CsvMapper();

        mapper.enable(CsvGenerator.Feature.STRICT_CHECK_FOR_QUOTING);


        schema = mapper.schemaFor(clazz).withNullValue("");

    }


    public String toCsvString(Object entity) throws IOException {

        return mapper.writer(schema).writeValueAsString(entity);

    }

}

以及简单的用法:


CsvEntityGenerator gen = new CsvEntityGenerator(EntityCsvRecord.class);

System.out.print(gen.toCsvString(new EntityCsvRecord("Na,me")));

System.out.print(gen.toCsvString(new EntityCsvRecord(null)));

System.out.print(gen.toCsvString(new EntityCsvRecord("Name")));

印刷:


8b572b1b-17c1-429d-887b-ec9af1c30d05,"Na,me",SOMETHING,123456,www.some.url

e86eacb1-d45e-4614-91bb-45f0d8840ea9,,SOMETHING,123456,www.some.url

e9627c32-6736-44a5-8eb2-7d153f86af20,Name,SOMETHING,123456,www.some.url

正如您所看到的,我们只创建一次CsvMapper并且CsvSchema当我们想要序列化实体时重用它。这是更快的方法。


查看完整回答
反对 回复 2023-12-13
  • 1 回答
  • 0 关注
  • 102 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信