从父子 ID 的原始数据创建 Json 层次结构

Create Json Hierarchy from from raw data of parent child id

数据列看起来像:

CompanyId,Parent Id
1,1
2,1
3,1
4,2
5,2

每家公司都属于某个母公司。我需要将此原始数据转换为以下 json 格式。

[
 {
   id : 1 
   child : [
            {
                id : 2
                child : [
                          {
                           id : 4
                          },
                          {
                           id : 5
                          }
                        ]
            },
            {
                id : 3
            }
           ]
  }
]

任何 java 代码实施都会有所帮助。

假设数据 table 如下所示:

Map<Integer, Integer> childToParent = new HashMap<>();
childToParent.put(1, 1);
childToParent.put(2, 1);
childToParent.put(3, 1);
childToParent.put(4, 2);
childToParent.put(5, 2);

我们可以创建一个 parent 到 children 映射:

Map<Integer, List<Integer>> parentToChildren = childToParent.entrySet().stream()
        .collect(Collectors.groupingBy(Map.Entry::getValue, Collectors.mapping(Map.Entry::getKey, Collectors.toList())));

为简单起见,我们同样创建一个Company class:

@Data
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Company {
    private final int id;
    @JsonProperty(value = "child")
    private List<Company> children;
}

然后创建Company objects:

Map<Integer, Company> idToCompany = childToParent.keySet().stream()
        .map(integer -> new Company(integer,  null))
        .collect(Collectors.toMap(Company::getId, company -> company));

现在我们可以为每个 parent:

设置 children
idToCompany.values().forEach(company -> {
    List<Integer> childrenIds = parentToChildren.get(company.getId());

    if(childrenIds != null){
        List<Company> children = childrenIds.stream()
                .filter(childId -> childId != company.getId()) // a company can't be a parent of itself
                .map(idToCompany::get)
                .collect(Collectors.toList());
        company.setChildren(children);
    }
});

现在我们可以像这样提取“头部”公司:

List<Company> companiesHeads = childToParent.entrySet().stream()
        .filter(childIdToParentId -> childIdToParentId.getKey().equals(childIdToParentId.getValue()))
        .map(Map.Entry::getKey)
        .map(idToCompany::get)
        .collect(Collectors.toList());

并以 JSON 格式打印到屏幕:

ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
System.out.println(mapper.writeValueAsString(companiesHeads));

输出:

[ {
  "id" : 1,
  "child" : [ {
    "id" : 2,
    "child" : [ {
      "id" : 4
    }, {
      "id" : 5
    } ]
  }, {
    "id" : 3
  } ]
} ]