通过反射将 Excel 和 CSV 转换为 Java 对象

2023-11-08 08:24:06 浏览数 (2)

将 Excel 或 CSV 文件转换为 Java 对象 (POJO) 以及将 Java 对象转换为 Excel 或 CSV 文件可能是一个复杂的过程,但如果使用正确的工具和技术,这个过程就会变得十分简单。在本文中,我们将了解如何利用一个 Java 反射的库来实现这个功能。

首先,我们将依赖关系添加到 Maven。

代码语言:javascript复制
<dependency>
  <groupId>com.adnanebk</groupId>
  <artifactId>excel-csv-converter</artifactId>
  <version>0.0.1-SNAPSHOT</version>
</dependency>

了解 POJO 类

在深入研究该库之前,让我们仔细看看作为数据模型的 Java 示例类:

代码语言:javascript复制
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@SheetDefinition(datePattern = "dd/MM/yyyy")
public class Product {

    @CellDefinition(0)
    private String name;

    @CellDefinition(1)
    private long price;

    @CellDefinition(2)
    @CellBoolean(trueValue = "yes",falseValue = "no")
    private boolean active;

    @CellDefinition(value = 3, title = "Promo price")
    private double promoPrice;

    // Additional fields...

    @CellEnum(enumsMapperMethod = "categoryMap")
    @CellDefinition(10)
    private Category category;

    @CellDefinition(11)
    private LocalDateTime localDateTime;

    private Map<Category,String> categoryMap(){
        return Map.of(Category.A,"Formatted A",
                      Category.B,"Formatted B");
    }
}

该类Product带有各种注释,这些注释在转换过程中起着至关重要的作用。每个字段都带有注释@CellDefinition,指示其在Excel 或 CSV 文件中的位置。

我们还可以定义单元格的标题,默认情况下,它会将字段的驼峰式名称转换为带空格的名称(例如:firstName=>First name)

@SheetDefinition注释提供了附加信息,例如将在日期字段类型转换期间使用的日期格式化模式。

枚举注释:@CellEnum(enumsMapperMethod = “categoryMap”)

Product类中,我们使用@CellEnum枚举 Category 字段中的注释。enumsMapperMethod 参数允许我们定义方法名称;此方法应返回一个映射,该映射定义枚举常量与 Excel/CSV 单元格中的格式化值之间的映射(转换)(默认情况下,将使用枚举常量),请注意,方法名称必须与 enumsMapperMethod 参数值相同。

[布尔注解:@CellBoolean(trueValue = “yes”,falseValue = “no”)]

在我们需要使用Boolean类型的字段中使用 @CellBoolean 注释,它有两个参数代表我们要在 Excel/CSV 字段中使用的格式值。

现在,让我们介绍 POJO 类的更新版本ProductV2

代码语言:javascript复制
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@SheetDefinition(includeAllFields = true,titles={"Name","Category","Date"})
public class ProductV2 {

    private String name;

    // Additional fields...

    private Category category;

    @IgnoreCell
    private LocalDateTime localDateTime;
}

@SheetDefinition通过类中提供的注释将字段映射到 Excel 文件中的相应单元格,将 Excel 文件转换为 POJO 变得更加简单。

当 includeAllFields 参数设置为 true 时,字段将根据其声明的顺序自动包含并映射到单元格中,并忽略使用 @IgnoreCell 注释进行注释的字段。

我们可以在标题参数中定义标题,条件是它们必须与字段的顺序一致。

将 Excel/CSV 转换为 POJO
代码语言:javascript复制
@RestController
@RequestMapping("excel/products")
public class ExcelFieldsController {
    private final ExcelHelper<Product> excelHelper = ExcelHelper.create(Product.class);

    @GetMapping
    public List<Product> excelToProducts(@RequestBody MultipartFile file){
        return excelHelper.toStream(file.getInputStream()).toList();
    }

       @GetMapping("/download")
    public ResponseEntity<InputStreamResource>
    downloadExcelFromProducts() {
        String filename = "products-"   LocalDate.now()   ".xlsx";
        InputStreamResource file = new InputStreamResource(excelHelper.toExcel(getProducts()));
        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename="   filename)
                .contentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"))
                .body(file);
    }
}

这同样适用于转换 CSV 文件,只是我们需要定义将使用的分隔符

代码语言:javascript复制
    private final CsvHelper<ProductV2> csvHelper = CsvHelper.create(ProductV2.class,";");

ReflectionUtil:动态检验类

ReflectionUtil 类是该 Java 库的支柱,通过 Java 反射的强大功能促进动态类检查和操作。ReflectionUtil 类的一个显著特点是为提高性能而进行的优化。在初始化过程中,所有的get、set和字段都会被快速加载并封装在 SheetField 中。这种有意识的操作最大限度地减少了后续操作中的反射查找需求,提高了整体效率。

主要方法:

public Object getValue(T obj):使用对象的 getter 方法检索字段的值。如果该字段是枚举,它会根据定义的枚举映射提供格式化值。

public void setValue(T obj, Object value):使用对象的 setter 方法设置对象中字段的值。它处理枚举值并确保正确的转换。

结论

通过利用这个自定义库,开发人员可以显着简化将 Excel 和 CSV 文件转换为Java 中的 POJO的过程。Java 反射的集成以及深思熟虑的设计考虑支持动态映射,使其成为数据处理任务的宝贵工具。

0 人点赞