猿问

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

我的 REST 服务正在接受一个class A包含objects B. 所需对象的行为是,如果有一些重复的条目,则需要添加权重。使用jackson序列化/反序列化要实现这一点,有两种方法:

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

  2. @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.


月关宝盒
浏览 113回答 3
3回答

江户川乱折腾

要实现这一点,有两种方法:如果存在具有相同名称的条目,则继承ArrayList并覆盖添加方法并添加逻辑以求和权重。@JsonDeserialize在反序列化 JSON 时使用。首选哪个选项,为什么?顺便说一下,您不应该使用这些方法中的任何一种。见下文:add()应避免覆盖执行计算的方法。您可以利用流来处理已添加到列表中的数据。Jackson 应该只用于 JSON 解析,而不用于执行业务逻辑。事实上,您应该做的是在控制器层接收 JSON,将其解析为列表,然后委托给服务层,您将在服务层执行分组和求和操作。此外,重要的是要提到您必须避免在计算中同时使用Float和Double类型,因为它们在精度方面存在问题。改用BigDecimal。最后,这是您的分组和求和方法BigDecimal:public List<B> groupByNameAndSumWeight(List<B> list) {&nbsp; &nbsp; return list.stream()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .collect(groupingBy(B::getName, reducing(BigDecimal.ZERO, B::getWeight, BigDecimal::add)))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .entrySet().stream()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .map(entry -> new B(entry.getKey(), entry.getValue()))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .collect(toList());}并确保您具有以下静态导入:import static java.util.stream.Collectors.groupingBy;import static java.util.stream.Collectors.reducing;import static java.util.stream.Collectors.toList;

蝴蝶刀刀

您可以处理服务中的对象列表或创建解释器来处理对象列表,而不是使用自定义实现来添加或使用 @JsonDeserialize。您可以将以下代码添加到进程列表中,&nbsp;objects&nbsp;=&nbsp;objects.stream().collect(Collectors.groupingBy(B::getName,&nbsp;Collectors.summingDouble(B::getWeight))) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.entrySet().stream().map(ele->&nbsp;new&nbsp;B(ele.getKey(),&nbsp;ele.getValue())) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.collect(Collectors.toList());希望能帮助到你。

蝴蝶不菲

这听起来像是区分控制器和服务层的基本原因。让控制器接受纯列表并将其交给进行处理的服务。@Controller class MyController {&nbsp; &nbsp; @Autowired MyService service;&nbsp; &nbsp; @PostMapping(..) void postList(@Body List<B> items) {&nbsp; &nbsp; &nbsp; &nbsp; service.accept(items);&nbsp; &nbsp; }}在服务中,您可以添加权重。@Service class MyService {&nbsp; &nbsp; JpaRepository<B> repository;&nbsp; &nbsp; public void accept(List<B> items) {&nbsp; &nbsp; &nbsp; &nbsp; List<B> summed =&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; items.stream().collect(groupingBy(B::getName, summarizingDouble(B::getWeight)))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.entrySet().stream().map(e -> new B(e.getKey(), e.getValue()))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.collect(toList());&nbsp; &nbsp; &nbsp; &nbsp; repository.save(summed);&nbsp; &nbsp; }}
随时随地看视频慕课网APP

相关分类

Java
我要回答