Java 将通用POJO写入CSV转换器
我的用例是编写一个通用的CSV转换器,它应该能够将任何JavaPOJO转换为CSV字符串 我的实施:Java 将通用POJO写入CSV转换器,java,csv,generics,amazon-kinesis-firehose,jackson-dataformat-csv,Java,Csv,Generics,Amazon Kinesis Firehose,Jackson Dataformat Csv,我的用例是编写一个通用的CSV转换器,它应该能够将任何JavaPOJO转换为CSV字符串 我的实施: public <T> List<String> convertToString(List<T> objectList) { List<String> stringList = new ArrayList<>(); char delimiter = ','; char quote = '"
public <T> List<String> convertToString(List<T> objectList) {
List<String> stringList = new ArrayList<>();
char delimiter = ',';
char quote = '"';
String lineSep = "\n";
CsvMapper mapper = new CsvMapper();
CsvSchema schema = mapper.schemaFor(!HOW_TO!);
for (T object : objectList) {
try {
String csv = mapper.writer(schema
.withColumnSeparator(delimiter)
.withQuoteChar(quote)
.withLineSeparator(lineSep)).writeValueAsString(object);
} catch (JsonProcessingException e) {
System.out.println(e);
}
}
return stringList;
}
公共列表转换字符串(列表对象列表){
List stringList=新建ArrayList();
字符分隔符=',';
字符引号=“”;
字符串lineSep=“\n”;
CsvMapper映射器=新的CsvMapper();
CsvSchema schema=mapper.schemaFor(!HOW_TO!);
for(T对象:对象列表){
试一试{
字符串csv=mapper.writer(架构
.withColumnSeparator(分隔符)
.withQuoteChar(quote)
.withLineSeparator(lineSep)).writeValueAsString(对象);
}捕获(JsonProcessingException e){
系统输出打印ln(e);
}
}
返回字符串列表;
}
我使用的是Jackson dataformat csv库,但我坚持使用!HOW_TO!部分,即如何从objectList中提取对象的.class。我在学习时遇到了类型擦除,因此我认为除了将.class作为函数的参数之外,不知何故是不可能的。但我也从通用实体us中提取此对象列表正在初始化Java反射,因此我无法选择提供.class参数
有解决办法吗
或
任何其他方法/库,在这些方法/库中,我可以将通用列表objectList转换为List csvList
,并具有添加分隔符、引号字符、行分隔符等功能
谢谢!有一个简单的选项。我在代码中添加了一些行来显示:
public <T> List<String> convertToString(List<T> objectList) {
if(objectList.isEmpty())
return Collections.emptyList();
T entry = objectList.get(0);
List<String> stringList = new ArrayList<>();
char delimiter = ',';
char quote = '"';
String lineSep = "\n";
CsvMapper mapper = new CsvMapper();
CsvSchema schema = mapper.schemaFor(entry.getClass());
for (T object : objectList) {
try {
String csv = mapper.writer(schema
.withColumnSeparator(delimiter)
.withQuoteChar(quote)
.withLineSeparator(lineSep)).writeValueAsString(object);
stringList.add(csv);
} catch (JsonProcessingException e) {
System.out.println(e);
}
}
return stringList;
}
公共列表转换字符串(列表对象列表){
if(objectList.isEmpty())
返回集合。emptyList();
T entry=objectList.get(0);
List stringList=新建ArrayList();
字符分隔符=',';
字符引号=“”;
字符串lineSep=“\n”;
CsvMapper映射器=新的CsvMapper();
CsvSchema schema=mapper.schemaFor(entry.getClass());
for(T对象:对象列表){
试一试{
字符串csv=mapper.writer(架构
.withColumnSeparator(分隔符)
.withQuoteChar(quote)
.withLineSeparator(lineSep)).writeValueAsString(对象);
stringList.add(csv);
}捕获(JsonProcessingException e){
系统输出打印ln(e);
}
}
返回字符串列表;
}
诀窍是获取列表中的一个元素。为了避免崩溃,我在开始时添加了一个小的数据完整性测试,在输入列表中没有项目的情况下返回一个不可修改的空列表。
然后检索对象的实例并使用该实例获取类
或者,如果convertToString方法位于参数化类中,则可以用稍微不同的方式执行该操作
public class GenericClass<T> {
private final Class<T> type;
public GenericClass(Class<T> type) {
this.type = type;
}
public Class<T> getMyType() {
return this.type;
}
}
公共类GenericClass{
私有最终类类型;
公共泛型类(类类型){
this.type=type;
}
公共类getMyType(){
返回此.type;
}
}
这个解决方案可以让你得到T类。我认为你不需要它来回答这个问题,但它可能会派上用场 由于Java如何处理泛型,这个问题似乎比大多数人希望的更难。Bruno的回答显示了一些选项,如果您可以做出某些假设或以某种方式构造代码,这些选项可能会起作用 另一个适用于您的案例的选项可以通过回答另一个问题找到: 在这里,您可以找到一篇文章的链接: 这描述了如何使用对象超类的ParameterizedType。您可以将其应用于您的
列表
对象,希望它对您有用。幸运的是,这只在这种情况下起作用,因为您将一个具有超类的对象作为参数,该超类的类型参数与您需要的匹配
实际上,一般来说,我们不能依赖于在运行时知道类型参数。我们最多可以使用类型标记(类型参数
Class
)我创建了一个类似于下面使用java反射的CSVUtil类
下面要使用的示例CSVUtil
假设POJO是一名学生
List<Student> StudentList = new ArrayList<Student>();
String StudentCSV = CSVUtil.toCSV(StudentList,' ',false);
import java.lang.reflect.Field;
import java.util.List;
import java.util.logging.Logger;
List StudentList=new ArrayList();
字符串StudentCSV=CSVUtil.toCSV(StudentList',false);
导入java.lang.reflect.Field;
导入java.util.List;
导入java.util.logging.Logger;
CSVUtil类
public class CSVUtil {
private static final Logger LOGGER = Logger.getLogger(CSVUtil.class .getName());
private final static char DEFAULT_SEPARATOR = ' ';
public static String toCSV(List<?> objectList, char separator, boolean displayHeader) {
StringBuilder result =new StringBuilder();
if (objectList.size() == 0) {
return result.toString();
}
if(displayHeader){
result.append(getHeaders(objectList.get(0),separator));
result.append("\n");
}
for (Object obj : objectList) {
result.append(addObjectRow(obj, separator)).append("\n");
}
return result.toString();
}
public static String getHeaders(Object obj,char separator) {
StringBuilder resultHeader = new StringBuilder();
boolean firstField = true;
Field fields[] = obj.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
String value;
try {
value = field.getName();
if(firstField){
resultHeader.append(value);
firstField = false;
}
else{
resultHeader.append(separator).append(value);
}
field.setAccessible(false);
} catch (IllegalArgumentException e) {
LOGGER.severe(e.toString());
}
}
return resultHeader.toString();
}
public static String addObjectRow(Object obj, char separator) {
StringBuilder csvRow =new StringBuilder();
Field fields[] = obj.getClass().getDeclaredFields();
boolean firstField = true;
for (Field field : fields) {
field.setAccessible(true);
Object value;
try {
value = field.get(obj);
if(value == null)
value = "";
if(firstField){
csvRow.append(value);
firstField = false;
}
else{
csvRow.append(separator).append(value);
}
field.setAccessible(false);
} catch (IllegalArgumentException | IllegalAccessException e) {
LOGGER.severe(e.toString());
}
}
return csvRow.toString();
}
}
公共类CSVUtil{
私有静态最终记录器Logger=Logger.getLogger(CSVUtil.class.getName());
私有最终静态字符默认分隔符=“”;
公共静态字符串toCSV(列表对象列表、字符分隔符、布尔显示标题){
StringBuilder结果=新建StringBuilder();
if(objectList.size()==0){
返回result.toString();
}
如果(显示标题){
append(getHeaders(objectList.get(0),分隔符));
结果。追加(“\n”);
}
用于(对象对象对象:对象列表){
结果.append(addObjectRow(obj,分隔符)).append(“\n”);
}
返回result.toString();
}
公共静态字符串getHeaders(对象对象对象,字符分隔符){
StringBuilder resultHeader=新建StringBuilder();
布尔值firstField=true;
字段字段[]=obj.getClass().getDeclaredFields();
用于(字段:字段){
字段。setAccessible(true);
字符串值;
试一试{
value=field.getName();
如果(第一个字段){
resultHeader.append(值);
firstField=false;
}
否则{
resultTheader.append(分隔符).append(值);
}
字段.setAccessible(false);
}捕获(IllegalArgumentException e){
记录器。严重(如toString())