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

我从存储库获取数据并将其放入 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) {

            ...

        }

    }

但是,我不明白为什么它会这样工作,我在文档中找不到任何血统线索。


有人能解开这个谜团吗?


慕森卡
浏览 104回答 1
1回答

ITMISS

整个技巧是启用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.urle86eacb1-d45e-4614-91bb-45f0d8840ea9,,SOMETHING,123456,www.some.urle9627c32-6736-44a5-8eb2-7d153f86af20,Name,SOMETHING,123456,www.some.url正如您所看到的,我们只创建一次CsvMapper并且CsvSchema当我们想要序列化实体时重用它。这是更快的方法。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java