[英]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
如您所見,我們只創建一次CsvMapper
和CsvSchema
,並在我們想要序列化實體時重用它。 這是更快的方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.