簡體   English   中英

為什么 Jackson 在重建配置模式以構建 CSV 的記錄行時包裝包含逗號的字符串?

[英]Why Jackson wrap the string containing comma when rebuilding the configuration schema for building a record line for a CSV?

我從存儲庫中獲取數據並將其放入 CSV。 為了建立記錄線,我使用 Jackson。 如果字段值包含逗號,我的目標是用雙引號將字段(字符串類型)括起來。 所以 output 應該是這樣的:

some-uuid-value、一些不帶逗號的字符串、SOMETHING、123456、www.some.url 等
some-uuid-value,"some string, but with comma", SOMETHING, 123456, www.some.url等
some-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) {
            ...
        }
    }

但是,我不明白為什么它會這樣工作,我在文檔中找不到任何下降線索。

有人能解開這個謎團嗎?

整個技巧是您啟用CsvGenerator.Feature.STRICT_CHECK_FOR_QUOTING功能。 從文檔:

確定在確定列值需要引用之前完成了多少工作的功能:當設置為 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

如您所見,我們只創建一次CsvMapperCsvSchema ,並在我們想要序列化實體時重用它。 這是更快的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM