[Bug] csv和xlsx两种模式不能共用同一个自定义Converter
- 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
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