Export Any Java Object to CSV/Excel with Reflection – A Universal Solution
This article demonstrates how to create a generic utility that uses Java reflection to export lists of arbitrary objects to CSV or Excel files, covering dependency setup, core implementation, custom annotation support, and practical usage examples.
Goal
Provide a universal way to export any Java class (e.g., User, Student, District) to CSV/Excel without writing class‑specific code.
Core Idea
Use reflection to read all fields of an object, convert each object to a Map<String, Object>, and then build CSV header and rows by iterating over the map entries.
Dependencies
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.15</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>3.15</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.69</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>Utility Class MyCsvFileUtil
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import java.io.*;
import java.lang.reflect.*;
import java.text.SimpleDateFormat;
import java.util.*;
@Slf4j
public class MyCsvFileUtil {
public static final String FILE_SUFFIX = ".csv";
public static final String CSV_DELIMITER = ",";
public static final String CSV_TAIL = "
";
protected static final String DATE_STR_FILE_NAME = "yyyyMMddHHmmssSSS";
/** Create CSV file */
public static void createCsvFile(String savePath, String contextStr) throws IOException {
File file = new File(savePath);
file.createNewFile();
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(contextStr.getBytes("gbk"));
}
}
/** Write content to file */
public static void writeFile(String fileName, String content) {
try (FileOutputStream fos = new FileOutputStream(fileName, true);
OutputStreamWriter writer = new OutputStreamWriter(fos, "GBK")) {
writer.write(content);
writer.flush();
} catch (Exception e) {
log.error("Write file exception|{}", e);
}
}
/** Build file name */
public static String buildCsvFileFileName(List dataList) {
return dataList.get(0).getClass().getSimpleName() + new SimpleDateFormat(DATE_STR_FILE_NAME).format(new Date()) + FILE_SUFFIX;
}
/** Build CSV header */
public static String buildCsvFileTableNames(List dataList) {
Map<String, Object> map = toMap(dataList.get(0));
StringBuilder sb = new StringBuilder();
for (String key : map.keySet()) {
sb.append(key).append(CSV_DELIMITER);
}
return sb.append(CSV_TAIL).toString();
}
/** Build CSV body */
public static String buildCsvFileBodyMap(List dataLists) {
List<Map<String, Object>> mapList = new ArrayList<>();
for (Object o : dataLists) {
mapList.add(toMap(o));
}
StringBuilder lineBuilder = new StringBuilder();
for (Map<String, Object> rowData : mapList) {
for (String key : rowData.keySet()) {
Object value = rowData.get(key);
if (Objects.nonNull(value)) {
lineBuilder.append(value).append(CSV_DELIMITER);
} else {
lineBuilder.append("--").append(CSV_DELIMITER);
}
}
lineBuilder.append(CSV_TAIL);
}
return lineBuilder.toString();
}
/** Convert object to map */
public static <T> Map<String, Object> toMap(T entity) {
Class<?> bean = entity.getClass();
Field[] fields = bean.getDeclaredFields();
Map<String, Object> map = new HashMap<>(fields.length);
for (Field field : fields) {
try {
if (!"serialVersionUID".equals(field.getName())) {
String methodName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
Method method = bean.getDeclaredMethod(methodName);
Object fieldValue = method.invoke(entity);
map.put(field.getName(), fieldValue);
}
} catch (Exception e) {
log.warn("toMap() Exception={}", e.getMessage());
}
}
return map;
}
}Basic Usage Example
@RequestMapping("/createCsvFileJcTest")
public void createCsvFileJcTest() {
List<District> districts = districtService.queryByParentCodes(Arrays.asList("110100"));
String fileName = "D:\\mycsv\\" + MyCsvFileUtil.buildCsvFileFileName(districts);
String tableNames = MyCsvFileUtil.buildCsvFileTableNames(districts);
MyCsvFileUtil.writeFile(fileName, tableNames);
String contentBody = MyCsvFileUtil.buildCsvFileBodyMap(districts);
MyCsvFileUtil.writeFile(fileName, contentBody);
}The generated CSV file contains a header row with field names and subsequent rows with corresponding values, handling nulls as "--".
Custom Column Names with Annotation
Define an annotation to specify a friendly column name:
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface JcExcelName {
String name() default "";
}Utility method to resolve column names:
public static <T> List<String> resolveExcelTableName(T entity) {
List<String> tableNamesList = new ArrayList<>();
Class<?> bean = entity.getClass();
for (Field field : bean.getDeclaredFields()) {
if (!"serialVersionUID".equals(field.getName())) {
String title = field.getName();
JcExcelName ann = field.getAnnotation(JcExcelName.class);
if (ann != null && StringUtils.hasLength(ann.name())) {
title = ann.name();
}
tableNamesList.add(title);
}
}
return tableNamesList;
}Build header using the resolved names:
public static String buildCsvFileTableNamesNew(List<String> nameList) {
StringBuilder sb = new StringBuilder();
for (String name : nameList) {
sb.append(name).append(MyCsvFileUtil.CSV_DELIMITER);
}
return sb.append(MyCsvFileUtil.CSV_TAIL).toString();
}Example:
User user = new User();
List<String> nameList = resolveExcelTableName(user);
String header = buildCsvFileTableNamesNew(nameList);
System.out.println(header);Diagram Overview
The approach works for any list of objects, producing correctly formatted CSV/Excel files with optional custom column titles.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
