如何为同一 DTO 属性指定 2 个名称

前言

我们在《实现DDD领域驱动设计》中谈到过输出 DTO 的最佳实践,其中一条是:

  • 保持输出 DTO 数量最少,尽可能重用。

但是,对于 2 个不同接口输出的同一 DTO 属性,客户端可能需要对应不同的名称,比如:

public class MyIODTO 
{
    [JsonPropertyName("pageNumer")] //用于 B 接口返回
    [JsonPropertyName("pageNum")] //用于 A 接口返回
    public int PageNum { get; set; }
}

这样显然无法编译成功:

那怎么实现呢?

解决方案

1. 冗余属性

输出 DTO 另外一条最佳实践:

  • 输出 DTO 可以包含比客户端代码中使用的更多的属性。

因此,我们可以增加一个属性,用于第 2 个名称,但是第 2 个属性只是用于返回第 1 个属性的值:

public class MyIODTO
{
    [JsonPropertyName("pageNum")]
    public int PageNum { get; set; }

    [JsonPropertyName("pageNumer")]
    public int PageNumer => PageNum;
}

2. 自定义转换器

上面的方式虽然可以解决问题,但是需要创建一个额外的属性。

更灵活的方式,是编写自定义转换器,自己处理 JSON 序列化的工作:

public class MyIOConverter : JsonConverter<MyIODTO>
{
    public override MyIODTO Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        throw new NotImplementedException();
    }

    public override void Write(
            Utf8JsonWriter writer, MyIODTO dto, JsonSerializerOptions options)
    {
        writer.WriteStartObject();

        writer.WriteNumber("pageNum", dto.PageNum);
        writer.WriteNumber("pageNumer", dto.PageNum);

        //序列化其他属性
        ...

        writer.WriteEndObject();
    }
}

然后为 DTO 指定自定义转换器:

[JsonConverter(typeof(MyIOConverter))]
public class MyIODTO
{
    public int PageNum { get; set; }
}

结论

冗余属性方式实现简单,而自定义转换器方式操作灵活,比如可以根据上下文来决定序列化成哪个名称。你可以按需选择。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果入参DTO和出参DTO都来自同一个表,可以考虑将它们合并为一个DTO。这个DTO应该包含与表中每个字段对应的属性,并且应该为这些属性提供适当的getter和setter方法。在这个DTO中,可以根据需要添加其他属性,以便在Controller中进行处理。 例如,如果你有一个名为"User"的表,那么可以创建一个名为"UserDTO"的DTO,其中包含与该表中每个字段对应的属性。例如: ```java public class UserDTO { private Long id; private String name; private Integer age; // getter and setter methods for all the properties } ``` 在Controller中,你可以使用这个DTO作为输入和输出参数。例如: ```java @RestController public class UserController { @Autowired private UserService userService; @GetMapping("/users/{id}") public UserDTO getUser(@PathVariable Long id) { User user = userService.getUserById(id); UserDTO userDTO = new UserDTO(); userDTO.setId(user.getId()); userDTO.setName(user.getName()); userDTO.setAge(user.getAge()); return userDTO; } @PostMapping("/users") public UserDTO createUser(@RequestBody UserDTO userDTO) { User user = new User(); user.setId(userDTO.getId()); user.setName(userDTO.getName()); user.setAge(userDTO.getAge()); userService.createUser(user); return userDTO; } } ``` 在这个例子中,"UserDTO"作为输入参数来获取用户,也作为输出参数来创建用户。注意,在这个例子中,使用了构造函数和setter方法来设置DTO属性,这是因为DTO属性与表中的字段一一对应。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值