java - 如何在 DTO 中返回枚举?
问题描述
我有一个订单实体:
public class Order {
private String name;
private Status status;//enum
//other fields, getters,setters
}
状态是具有很多值的枚举(假设有 30 个状态)。我创建了OrderDto
和OrderMapper
. 我想将我的订单转换为OrderDto
. 我应该如何处理Status
枚举?
我应该创建StatusDto
枚举和Status converter/mapper
或使用域中的枚举还是作为字符串Order
返回?Status.FOO.name()
public class OrderDto {
private String name;
private ??? status;//enum or String or another(dto) enum?
}
解决方案
如果你在你的Status
枚举中使用OrderDto
它,你将它与你的实体结合起来。因此,如果您更改实体层,您可以轻松地将 API 更改为客户端。
假设OrderDto
使用 java 对象序列化将其序列化以将其发送到客户端。如果客户端反序列化它,它需要实体层的类。这通常不是你想要的。
如果OrderDto
通过 JSON 序列化,则通常使用枚举的名称。这意味着如果您Status
对实体层中的枚举进行更改。它会立即更改发送到客户端的 JSON。
我会将它与另一个StatusDto
枚举解耦,并使用Map
. Status
如果实体更细粒度,这也是有意义的StatusDto
,例如
public class StatusMapper {
private Map<Status, StatusDto> toDto = new HashMap<>();
public StatusMapper(){
toDto.put(Status.PLACED, StatusDto.IN_PROCESS);
toDto.put(Status.CONFIRMED, StatusDto.IN_PROCESS);
toDto.put(Status.SHIPPED, StatusDto.IN_DELIVERY);
}
public StatusDto map(Status status){
StatusDto dto = toDto.get(status)
if(dto == null){
// default status or exception ?
}
return dto;
}
}
这种映射很容易测试。当使用 switch 而不是 aMap
时,很难测试默认情况。
编辑
与简单的 switch 语句相比,这是很多开销。为什么默认值很难测试?
首先我想说,下面的例子是基于Java的。也许有些语言没有这个问题。
假设您已经定义了以下枚举:
public enum Status {
S1, S2, S3;
}
通常,当您实现映射时,源值和目标值之间存在一对一的关系。因此,使用开关的映射将如下所示:
public String map(Status status) {
switch(status) {
case S1: return "State1";
case S2: return "State2";
case S3: return "State3";
default: throw new IllegalArgumentException("Unknown status");
}
}
现在尝试编写一个涵盖默认情况的测试。
您不能传递
Status
将执行默认案例的枚举,因为所有枚举值都包含在它们的案例中。默认情况的本质是仅在添加新枚举时才执行。但是您不能仅出于测试目的添加新枚举。不允许子类化。枚举是最终的。通常添加默认情况是为了提示开发人员记住,如果添加了新的枚举,则需要做一些工作。您不能通过
null
,因为它导致NullPointerException
(在 Java 中),因为开关使用枚举的序数值。您可以在字节码中看到这一点。
使用 Map 方法,我可以通过null
. 由于地图没有映射,因此返回 null ,因此覆盖了“默认”。当然,这与通过未知枚举并不完全相同,但对我来说,这是测试它的最佳折衷方案。
推荐阅读
- php - php钠函数中的ENCONDING CHARACTERS问题
- android - 如何修复 android.widget.TextView() 需要 api 21 错误
- objective-c - 用石英 2D 从透明 png 交换 UIImage 上的颜色通道
- julia - 如何在 Julia 的 TimeSeries 中增加价值
- sql - 如何使用输入参数文件路径从 plpgsql 函数中复制
- python - 如何获取包含管道的 Python 子进程命令的输出?
- r - 如何查看并行调整 mlr 的中间结果?
- c++ - 如何在模板函数中根据对象的类型构造不同的对象?
- c# - 将字符串作为参数传递:它是复制还是引用?我很困惑
- r - 为什么 predict.lm 和矩阵乘法给出不同的预测?