首页 > 解决方案 > 根据 ID 分组 JSON

问题描述

我有一个json

{  
  "content": [
    {
      "idnumber": "666",
      "name": "mark",
      "type": "band",
      "tools": [
        {
          "idtools": "5657",
          "blabla": null,
          "blabla": false,
        }
      ]
    },
    {
      "idnumber": "666",
      "name": "mark",
      "type": "band",
      "tools": [
        {
          "idtools": "5658",
          "blabla": null,
          "blabla": false
        }
      ]
    }
  ]
}

在内容数组中,我有 2 个 json。我想将我的 json 更改为此,因为它们具有相同的 ID 号。

{  
  "content": [
    {
      "idnumber": "666",
      "name": "mark",
      "type": "band",
      "tools": [
        {
          "idtools": "5657",
          "blabla": null,
          "blabla": false,
        },
        {
          "idtools": "5658",
          "blabla": null,
          "blabla": false
        }
      ]
    }
  ]
}

如何使用 distinct 或 filter 做到这一点?

我试图区分它并映射它,但仍然有错误。

标签: javaspringjava-8collectors

解决方案


假设以下对象与您的 JSON 结构匹配(为简洁起见,我使用 Lombok):

@Data
@AllArgsConstructor
@NoArgsConstructor
class Content {
    int idNumber;
    String name;
    String type;
    List<Tool> tools;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class Tool {
    int idTools;
    String blabla;
}

您可以将 Stream API 与groupingBybyidreduce值合二为一。

 List<Content> mergedContents = contents.stream()
     .collect(Collectors.groupingBy(Content::getIdNumber))
     .values()
     .stream()
     .reduce(
          new ArrayList<>(),                               // mutable List
          (left, right) -> {
              Content content = right.get(0);              // they are same (by id)
              List<Tool> tools = right.stream()            // from each new list
                      .flatMap(c -> c.getTools().stream()) // .. flatmap the tools
                      .collect(Collectors.toList());       // .. and extract to a list
              content.setTools(tools);                     // set the List<Tool>
              left.add(content);                           // add the Content
              return left;                                 // return the left list
          },
          (left, right) -> left);                          // only for parallel Stream

Collectors.groupingBy(Content::getIdNumber)产生的结构来自Map<Integer, List<Content>>. 随后对映射值的可变归约 ( Collection<List<Content>>) 将每个 with same 合并List<Content>Content.id一个Contentwith flatmapped List<Tools>Content作为归约的结果,返回带有这些修改的列表。

样本数据

List<Content> contents = new ArrayList<>();
contents.add(new Content(666, "Mark", "Band", 
        Collections.singletonList(new Tool(5657, null))));
contents.add(new Content(666, "Mark", "Band", 
        Collections.singletonList(new Tool(5658, null))));

List<Content> mergedContents = /* solution */

mergedContents.forEach(System.out::println);

Main.Content(idNumber=666, name=Mark, type=Band, tools=[Main.Tool(idTools=5657, blabla=null), Main.Tool(idTools=5658, blabla=null)])

这等于您的 JSON 样本。


推荐阅读