Skip to content

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

Description

@luo-zhan

Search before asking

  • I searched in the issues and found nothing similar.

Fesod version

2.0.1-incubating

JDK version

8

Operating system

macOS 15.2

Steps To Reproduce

单测如下:

class FesodCsvConverterKeyNativeTest {

    /** JVM 全局静态写转换器表的初始快照(本类首个测试运行前保存) */
    private static Map<Object, Object> 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<Object, Object> globalWriteConverterMap() throws Exception {
        Field field = DefaultConverterLoader.class.getDeclaredField("defaultWriteConverter");
        field.setAccessible(true);
        return (Map<Object, Object>) field.get(null);
    }

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

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

        @Override
        public WriteCellData<?> convertToExcelData(WriteConverterContext<Boolean> 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?

  • I'm willing to submit a PR!

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions