Repository navigation
[Enhancement] Support annotation-based dictionary conversion #198
Description
Activity
Hi @psxjoy, I have been thinking about this for the last week and have put together a concrete design for it. Please, read it carefully or pin someone who can read it :)
Proposal:
@DictFormatfor code-label mappingThis issue is labelled
planningand has no design written down yet, so here is a concrete proposal to react to. I would rather agree on the shape here than open a PR that guesses it.TL;DR
- Problem: a field stores a code (
1), the sheet should show a label (Success). Today that needs a hand-writtenConverterclass per dictionary. - Proposal: an annotation -
@DictFormat({"1=Success", "0=Failure"})- plus an enum-backed form for dictionaries that already exist in the domain model. - Scope: read and write,
String/Integer/Long/Short/Byte/Boolean/BigInteger; anunmapped()policy for partial dictionaries.
Proposed API
public @interface DictFormat { String[] value() default {}; // "code=label" entries Class<? extends Dict> type() default Dict.None.class; // or an enum implementing Dict UnmappedEnum unmapped() default UnmappedEnum.THROW; // THROW | NULL | PASS_THROUGH }
Inline form, for a mapping used in one place:
@ExcelProperty("Status") @DictFormat({"1=Success", "0=Failure"}) private Integer status;
Enum-backed form, for a dictionary that already exists:
public enum Status implements Dict { SUCCESS("1", "Success"), FAILURE("0", "Failure"); // code() and label() } @ExcelProperty("Status") @DictFormat(type = Status.class) private Integer status;
Dictwould be a two-method interface (code(),label()) that users implement.Proposed behaviour
Field types. Codes would be written as strings in the annotation and converted to the field type, by reusing the registered
<Type>StringConverterrather than any new logic.I would propose an allowlist rather than "any type with a registered converter", because the types left out fail silently rather than loudly.
Partial dictionaries. The annotation replaces the converter body, so it has to decide what happens to a value the dictionary does not cover. I would make that an explicit choice rather than pick one behaviour for everybody:
Policy Write Read THROW(proposed default)fail, naming the value fail, naming the label NULLempty cell nullfieldPASS_THROUGHvalue unchanged cell text unchanged Existing converters.
@DictFormatwould only install a converter on a field that does not already declare one, so an explicit@ExcelProperty(converter = ...)keeps winning.Validation. What would be rejected:
- Malformed configuration - an entry that is not
"code=label", or an annotation that gives both the inline entries and an enumtype, or neither of them. - Ambiguity - the same code or the same label used twice, including two codes that become one value after conversion (
"1"and"01"on anIntegerfield). - A code the field type cannot hold -
"abc"on anIntegerfield, but also"1.9"or a value pastInteger.MAX_VALUE, which the numeric converters would otherwise truncate or wrap instead of failing. - An empty label -
{"1=", "0=Failure"}, where code1has nothing after the=. Writing a1would leave the cell empty, and an empty cell comes back asnullinstead of1, so the value would be lost on the way back.
Questions
"code=label"strings, or a nested@DictEntry(code = ..., label = ...)? This is the one I would most like decided before writing anything. The examples above use the string form throughout, but only because a proposal needs one syntax to show - either would work:
@DictFormat({"1=Success", "0=Failure"}) @DictFormat({ @DictEntry(code = "1", label = "Success"), @DictEntry(code = "0", label = "Failure") })
Strings are shorter and read like the mapping they describe, but the compiler cannot see inside them -
"1:Success"compiles and fails only when the model is built. Separate attributes make a missing code or label a compile error, and leave room for anything per-entry we might want later.- Name/Place
@DictFormatis chosen to sit beside@NumberFormat/@DateTimeFormatinannotation/format. Open to alternatives.
Did I miss something? Happy to adjust any of the above.
- Problem: a field stores a code (
Hi @delei, my apologies for pinning you, but I am afraid that my proposal may be lost in the sea of notifications, since this is an old issue. Should I create a new one and reference this or just wait🙏🏻
Reacted by DeleiGuoIt's okay. We won’t overlook it.
You can also create a new one to link to it. It’s just that this new proposal hasn’t yet attracted the community’s attention and support.Reacted by Nikita KuprinsAs there has been no new version update for a long time, I took a look at the issues related to the translation of data dictionaries. If this PR Add composable annotations support is merged into the new version as soon as possible, it can solve many similar issues. Custom translation, dictionary translation, enum translation will be very simple. There is no need to pay too much attention to the business itself. Just leave the implementation method to the users.
关于这个问题,我觉得枚举转换带有业务含义,不是本项目该专注的工作,所以应该是先自行做好字段转换工作,再由Fesod导出。
我之前正好开发了个字段转换组件Transformer,使用效果如下:
/** * 单据类型 */ private String orderType; /** * 单据类型(描述) */ @ExcelProperty("单据类型") @TransformEnum(OrderTypeEnum.class) //将字段orderType的值经过枚举类的转换,设值到orderTypeName字段中 private String orderTypeName;
OrderTypeEnum枚举类定义,实现了Dict接口(也是单独一个枚举增强的项目EasyEnum,被Transformer引入),类定义变得非常简洁:public enum OrderTypeEnum implements Dict<String> { REQUIREMENT_ORDER("REQUIREMENT_ORDER", "要货单"), REFUND_ORDER("REFUND_ORDER", "退货单"); OrderTypeEnum(String type, String desc) { init(type, desc); // 使用Dict方法初始化,自动拥有get方法 } }
Transformer不仅可以转换枚举类,也包括数据字典、rpc、db、自定义任何你想要的转换,然后使用时只需要用一行注解,非常方便。ps.不一定强制使用Dict接口,如果你有自己的枚举接口,可以很方便的基于Transformer的能力写一个自定义枚举转换器注解
触发转换的方式有两种:
- 自动全局开启,在启动类上使用
@EnableTransform,通过ResponseBodyAdvice自动对所有controller的响应体开启转换 - 手动使用,TransformUtil.transform(result);
我认为除了“boolean转字符串”这种纯文本转换可以由Fesod来实现,但其他包括枚举转换、id->name这种有业务含义的字段转换都不该由Fesod负责,各司其职。
其实,说到这里,上面的方式和自定义一个EnumConverter注入到Fesod的效果差不多,但是Transfermer专注字段转换能力,让每个工作变得更专注和解耦,扩展性更高
另外,为了简化Fesod的使用,还开发了一个注解式导出的组件,也可以顺便看看,一个注解,就可以把查询接口变成导出接口,性能上还支持游标分页、流式传输ExportExcel
@ExportExcel(limit = 50000, type = ExportType.CSV) @PostMapping("/api/requirement/deliveryCostStoreFee/paging") public Response<Paging<DeliveryCostStoreFreeDTO>> paging(@RequestBody PagingDeliveryCostStoreFreeRequest request) {
配合Transformer有最简单的开发体验,已经在生产环境使用
- 自动全局开启,在启动类上使用
- changed the title
[-]希望支持注解字典转换[/-][+][Enhancement] Support annotation-based dictionary conversion[/+]on Oct 5, 2026 - addedenhancementNew feature or requestNew feature or requesthelp wantedExtra attention is neededExtra attention is neededand removedplanningIt may be developed laterIt may be developed later
on Oct 5, 2026
非常需要这个功能,之前都是自定义处理器来着