递归对象写入平面 csv 文件
Recursive object write to flat csv file
我需要写这样的对象
class User {
UUID id;
String name;
Role role;
}
class Role {
String name;
LocalDate activeFrom;
Authority owner;
}
class Authority {
String name;
}
棘手的想法是 csv 写入应该通过对象树递归地工作。还需要将 LocalDate 写成字符串,如 2019-11-05 f.e.;
生成的 csv 文件应该是平面的,看起来像:
user.id,user.name,user.role.name,user.role.activeFrom,user.role.owner.name
// 示例值
我已经尝试过 OpenCsv:
StatefulBeanToCsv<User> beanToCsv = new StatefulBeanToCsvBuilder<User>(printWriter).build();
try {
beanToCsv.write(users);
} catch (CsvDataTypeMismatchException | CsvRequiredFieldEmptyException e) {
e.printStackTrace();
}
printWriter.close();
和 Univocity 解析器:
CsvWriterSettings settings = new CsvWriterSettings();
ObjectRowWriterProcessor processor = new ObjectRowWriterProcessor();
settings.setRowWriterProcessor(processor);
processor.convertType(User.class, );
到目前为止运气不好。他们只能序列化为 csv 顶级对象。同样在 OpenCsv 中,我在序列化 LocalDate 时遇到了问题。
你能帮助我吗?建议方法或库?
由于我没有得到任何答案,我将描述我的解决方案。
我使用了图书馆:
http://super-csv.github.io/super-csv/index.html
和扩展名:
https://super-csv.github.io/super-csv/dozer.html
代码:
import org.supercsv.io.dozer.CsvDozerBeanWriter;
import org.supercsv.prefs.CsvPreference;
import java.io.IOException;
import java.io.Writer;
static final String[] FIELD_MAPPING = new String[]{
"user.id", "user.name", "user.role.name", "user.role.activeFrom", "user.role.owner.name"
};
try (var beanWriter = new CsvDozerBeanWriter(printWriter, CsvPreference.STANDARD_PREFERENCE)) {
beanWriter.configureBeanMapping(User.class, FIELD_MAPPING);
beanWriter.writeHeader(FIELD_MAPPING);
for (User user : users) {
beanWriter.write(user);
}
}
printWriter.close();
https://super-csv.github.io/super-csv/xref-test/org/supercsv/example/dozer/Writing.html
以及如何测试它:
@Test
void status_written_in_csv_format() {
// Setup
WriteCsvToResponse objectUnderTest = new WriteCsvToResponse ();
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);
// Given
Status status = ...
// When
objectUnderTest.writeStatus(printWriter, status);
// Then
String actualCsv = stringWriter.toString();
assertThat(actualCsv.split("\n"))
.as("Produced CSV")
.containsExactly(
"id,storeId,status",
"42,142,OK");
}
在 univocity-parsers 上,无需任何映射,您只需使用 @Nested
注释嵌套对象即可。
class User {
...
@Nested
Role role;
}
我需要写这样的对象
class User {
UUID id;
String name;
Role role;
}
class Role {
String name;
LocalDate activeFrom;
Authority owner;
}
class Authority {
String name;
}
棘手的想法是 csv 写入应该通过对象树递归地工作。还需要将 LocalDate 写成字符串,如 2019-11-05 f.e.;
生成的 csv 文件应该是平面的,看起来像:
user.id,user.name,user.role.name,user.role.activeFrom,user.role.owner.name
// 示例值
我已经尝试过 OpenCsv:
StatefulBeanToCsv<User> beanToCsv = new StatefulBeanToCsvBuilder<User>(printWriter).build();
try {
beanToCsv.write(users);
} catch (CsvDataTypeMismatchException | CsvRequiredFieldEmptyException e) {
e.printStackTrace();
}
printWriter.close();
和 Univocity 解析器:
CsvWriterSettings settings = new CsvWriterSettings();
ObjectRowWriterProcessor processor = new ObjectRowWriterProcessor();
settings.setRowWriterProcessor(processor);
processor.convertType(User.class, );
到目前为止运气不好。他们只能序列化为 csv 顶级对象。同样在 OpenCsv 中,我在序列化 LocalDate 时遇到了问题。 你能帮助我吗?建议方法或库?
由于我没有得到任何答案,我将描述我的解决方案。 我使用了图书馆:
http://super-csv.github.io/super-csv/index.html
和扩展名:
https://super-csv.github.io/super-csv/dozer.html
代码:
import org.supercsv.io.dozer.CsvDozerBeanWriter;
import org.supercsv.prefs.CsvPreference;
import java.io.IOException;
import java.io.Writer;
static final String[] FIELD_MAPPING = new String[]{
"user.id", "user.name", "user.role.name", "user.role.activeFrom", "user.role.owner.name"
};
try (var beanWriter = new CsvDozerBeanWriter(printWriter, CsvPreference.STANDARD_PREFERENCE)) {
beanWriter.configureBeanMapping(User.class, FIELD_MAPPING);
beanWriter.writeHeader(FIELD_MAPPING);
for (User user : users) {
beanWriter.write(user);
}
}
printWriter.close();
https://super-csv.github.io/super-csv/xref-test/org/supercsv/example/dozer/Writing.html
以及如何测试它:
@Test
void status_written_in_csv_format() {
// Setup
WriteCsvToResponse objectUnderTest = new WriteCsvToResponse ();
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);
// Given
Status status = ...
// When
objectUnderTest.writeStatus(printWriter, status);
// Then
String actualCsv = stringWriter.toString();
assertThat(actualCsv.split("\n"))
.as("Produced CSV")
.containsExactly(
"id,storeId,status",
"42,142,OK");
}
在 univocity-parsers 上,无需任何映射,您只需使用 @Nested
注释嵌套对象即可。
class User {
...
@Nested
Role role;
}