为了账号安全,请及时绑定邮箱和手机立即绑定

将 json 对象反序列化为具有与 ArrayList 不同行为的列表的最佳方法是什么

将 json 对象反序列化为具有与 ArrayList 不同行为的列表的最佳方法是什么

月关宝盒 2023-06-14 16:01:31
我的 REST 服务正在接受一个class A包含objects B. 所需对象的行为是,如果有一些重复的条目,则需要添加权重。使用jackson序列化/反序列化要实现这一点,有两种方法:如果存在具有相同名称的条目,则继承ArrayList并覆盖添加方法并添加逻辑以求和权重。@JsonDeserialize在反序列化 JSON 时使用。首选哪个选项,为什么?class A {  List<B> objects;  // Getters and Setters}class B {  String name;  Float weight;  boolean equals() {    // compares name.  }}示例 JSON{objects:[{name:"X", weight:10.2},{name:"Y",weight:12.5},{name:"X", weight:20}]}这应该产生一个大小为 2 的对象列表,其值为name:X,weight:30.2 and name:Y,weight:12.5.
查看完整描述

3 回答

?
江户川乱折腾

TA贡献1851条经验 获得超5个赞

要实现这一点,有两种方法:

  1. 如果存在具有相同名称的条目,则继承ArrayList并覆盖添加方法并添加逻辑以求和权重。

  2. @JsonDeserialize在反序列化 JSON 时使用。

首选哪个选项,为什么?

顺便说一下,您不应该使用这些方法中的任何一种。见下文:

  1. add()应避免覆盖执行计算的方法。您可以利用流来处理已添加到列表中的数据。

  2. Jackson 应该只用于 JSON 解析,而不用于执行业务逻辑。

事实上,您应该做的是在控制器层接收 JSON,将其解析为列表,然后委托给服务层,您将在服务层执行分组和求和操作。

此外,重要的是要提到您必须避免在计算中同时使用FloatDouble类型,因为它们在精度方面存在问题。改用BigDecimal

最后,这是您的分组和求和方法BigDecimal

public List<B> groupByNameAndSumWeight(List<B> list) {

    return list.stream()

            .collect(groupingBy(B::getName, reducing(BigDecimal.ZERO, B::getWeight, BigDecimal::add)))

            .entrySet().stream()

            .map(entry -> new B(entry.getKey(), entry.getValue()))

            .collect(toList());

}

并确保您具有以下静态导入:


import static java.util.stream.Collectors.groupingBy;

import static java.util.stream.Collectors.reducing;

import static java.util.stream.Collectors.toList;


查看完整回答
反对 回复 2023-06-14
?
蝴蝶刀刀

TA贡献1801条经验 获得超8个赞

您可以处理服务中的对象列表或创建解释器来处理对象列表,而不是使用自定义实现来添加或使用 @JsonDeserialize。您可以将以下代码添加到进程列表中,

 objects = objects.stream().collect(Collectors.groupingBy(B::getName, Collectors.summingDouble(B::getWeight)))
            .entrySet().stream().map(ele-> new B(ele.getKey(), ele.getValue()))
            .collect(Collectors.toList());

希望能帮助到你。


查看完整回答
反对 回复 2023-06-14
?
蝴蝶不菲

TA贡献1810条经验 获得超4个赞

这听起来像是区分控制器和服务层的基本原因。让控制器接受纯列表并将其交给进行处理的服务。


@Controller class MyController {

    @Autowired MyService service;

    @PostMapping(..) void postList(@Body List<B> items) {

        service.accept(items);

    }

}

在服务中,您可以添加权重。


@Service class MyService {

    JpaRepository<B> repository;

    public void accept(List<B> items) {

        List<B> summed = 

            items.stream().collect(groupingBy(B::getName, summarizingDouble(B::getWeight)))

             .entrySet().stream().map(e -> new B(e.getKey(), e.getValue()))

             .collect(toList());

        repository.save(summed);

    }

}


查看完整回答
反对 回复 2023-06-14
  • 3 回答
  • 0 关注
  • 114 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信