apache / apache/fesod

[Bug] csv和xlsx两种模式不能共用同一个自定义Converter

Open
#1,045 3 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
Java
Stars
6.2k
Forks
532
Avg merge
1d 3h
Merged PRs (30d)
42

Description

### Search before asking

- [x] I searched in the [issues](https://github.com/apache/fesod/issues) and found nothing similar.

### Fesod version

2.0.1-incubating

### JDK version

8

### Operating system

macOS 15.2

### Steps To Reproduce

单测如下:
```java
class FesodCsvConverterKeyNativeTest {

/** JVM 全局静态写转换器表的初始快照(本类首个测试运行前保存) */
private static Map pristineConverterMap;

@BeforeAll
static void snapshotGlobalConverterMap() throws Exception {
pristineConverterMap = new HashMap<>(globalWriteConverterMap());
}

@BeforeEach
void restoreGlobalConverterMap() throws Exception {
Field field = DefaultConverterLoader.class.getDeclaredField("defaultWriteConverter");
field.setAccessible(true);
// 用快照的拷贝整体替换,抹掉此前测试 registerConverter 留下的全局污染
field.set(null, new HashMap<>(pristineConverterMap));
}

@SuppressWarnings("unchecked")
private static Map globalWriteConverterMap() throws Exception {
Field field = DefaultConverterLoader.class.getDeclaredField("defaultWriteConverter");
field.setAccessible(true);
return (Map) field.get(null);
}

/** 内联自定义转换器:Boolean -> 是/否 */
static class BooleanToChineseConverter implements Converter {
@Override
public Class supportJavaTypeKey() {
return Boolean.class;
}

@Override
public CellDataTypeEnum supportExcelTypeKey() {
// 返回 null 表示匹配所有 Excel 类型 —— 注册 key 为 (Boolean, null)
return null;
}

@Override
public WriteCellData convertToExcelData(WriteConverterContext context) {
Boolean value = context.getValue();
if (Boolean.TRUE.equals(value)) {
return new WriteCellData<>("是");
}
if (Boolean.FALSE.equals(value)) {
return new WriteCellData<>("否");
}
return new WriteCellData<>("");
}
}


@Test
@DisplayName("xlsx 下自定义转换器正常生效:Boolean 输出「是」✅")
void xlsxShouldApplyCustomConverter(@TempDir Path tempDir) throws Exception {
File file = tempDir.resolve("custom.xlsx").toFile();

FesodSheet.write(file)
.excelType(ExcelTypeEnum.XLSX)
.registerConverter(new BooleanToChineseConverter())
.sheet()
.doWrite(Collections.singletonList(Collections.singletonList(Boolean.TRUE)));

try (Workbook workbook = WorkbookFactory.create(file)) {
String cellValue = workbook.getSheetAt(0).getRow(0).getCell(0).getStringCellValue();
System.out.println("xlsx + 自定义转换器: " + cellValue);
// targetCellDataType 未被改写(null),按 (Boolean, null) 命中自定义转换器
assertEquals("是", cellValue);
}
}

@Test
@DisplayName("CSV 下同一转换器被内置 String 转换器静默顶替:Boolean 输出 true 而非「是」(缺陷复现❌)")
void csvShouldSilentlyReplaceCustomConverter(@TempDir Path tempDir) throws Exception {
File file = tempDir.resolve("replaced.csv").toFile();

FesodSheet.write(file)
.excelType(ExcelTypeEnum.CSV)
.charset(StandardCharsets.UTF_8)
.registerConverter(new BooleanToChineseConverter())
.sheet()
.doWrite(Collections.singletonList(Collections.singletonList(Boolean.TRUE)));

String content = new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8);
System.out.println("CSV + 自定义转换器: " + content);
// 强制按 (Boolean, STRING) 查找,key (Boolean, null) 的自定义转换器未命中,
// 被内置 BooleanStringConverter 顶替,输出 value.toString() 即 true/false
assertEquals("\uFEFFtrue\r\n", content);
}

```

### Current Behavior

不能共用同一个Converter,csv模式下被内置 String 转换器静默顶替

### Expected Behavior

能共用同一个Converter

### Anything else?

_No response_

### Are you willing to submit a PR?

- [x] I'm willing to submit a PR!

Contributor guide

Open the contributing guide

Research direction

Start with the FesodCsvConverterKeyNativeTest reproduction and inspect DefaultConverterLoader.defaultWriteConverter together with the converter registration and lookup paths used by XLSX and CSV. Run both tests to compare their converter keys; done means the same custom Boolean converter produces 「是」 in both formats and the regression tests pass.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
74/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.