Home > Back-end >  Java JSON tree structure creation from existing data
Java JSON tree structure creation from existing data

Time:02-01

Need your help with creating a JSON tree structure from available data. This is what is available with me right now,

Data in DB

The same data in json format is as below,

{
"employees": [
  {
    "empId": 1,
    "empName": "Alex",
    "empGroupId": 3,
    "empLevel": 0
  },
  {
    "empId": 42,
    "empName": "Sam",
    "empGroupId": 3,
    "empLevel": 1
  },
  {
    "empId": 22,
    "empName": "Max",
    "empGroupId": 3,
    "empLevel": 2
  },
  {
    "empId": 54,
    "empName": "Ervin",
    "empGroupId": 3,
    "empLevel": 3
  },
  {
    "empId": 1,
    "empName": "Alex",
    "empGroupId": 5,
    "empLevel": 0
  },
  {
    "empId": 42,
    "empName": "Sam",
    "empGroupId": 5,
    "empLevel": 1
  },
  {
    "empId": 22,
    "empName": "Max",
    "empGroupId": 5,
    "empLevel": 2
  },
  {
    "empId": 68,
    "empName": "Jack",
    "empGroupId": 5,
    "empLevel": 3
  },
  {
    "empId": 1,
    "empName": "Alex",
    "empGroupId": 7,
    "empLevel": 0
  },
  {
    "empId": 38,
    "empName": "Mark",
    "empGroupId": 7,
    "empLevel": 7
  },
  {
    "empId": 12,
    "empName": "Danny",
    "empGroupId": 7,
    "empLevel": 2
  },
  {
    "empId": 1,
    "empName": "Alex",
    "empGroupId": 4,
    "empLevel": 0
  },
  {
    "empId": 38,
    "empName": "Mark",
    "empGroupId": 4,
    "empLevel": 1
  },
  {
    "empId": 55,
    "empName": "Kate",
    "empGroupId": 4,
    "empLevel": 2
  }
]
}

I want to create a JSON tree structure which will map all the employees in hierarchical manner. Such that all the common employees will appear only once and according to their levels.

So basically, empName will have a unique empId associated with it. Multiple employees can be part of employee group [indicated by empGroupId]. The empLevel indicates level of employee, 0 being top person, then 1, and so on...

For e.g, if we consider first 8 rows in table above, it contains 2 empGroupIds, 3 & 5. Alex, Sam and Max are the employees common in both groups with levels 0,1,2 respectively. Ervin and Jack are the last level at 3. And since their top 3 members are same, the final structure will have: Alex -> Sam -> Max -> [Ervin, Jack]

So below is what I want to generate,

[{
  "empName":"Alex",
  "empId" : 1,
  "empLevel" : 0,
  "children" :[{
    "empName":"Sam",
    "empId" : 42,
    "empLevel" : 1,
    "children" : [{
        "empName":"Max",
        "empId" : 22,
        "empLevel" : 2,
        "children": [{
            "empName":"Ervin",
            "empId" : 54,
            "empLevel" : 3            
            },{
            "empName":"Jack",
            "empId" : 68,
            "empLevel" : 3 
        }]
    }]
  },
  {
    "empName":"Mark",
    "empId" : 38,
    "empLevel" : 1,
    "children":[{
        "empName":"Danny",
        "empId" : 12,
        "empLevel" : 2
        },{
        "empName":"Kate",
        "empId" : 55,
        "empLevel" : 2      
    }]
  }]
}]

So far I have created a sample program to read the JSON file and mapped the employees. However not sure how to approach the design for this tree structure. This is what I have right now,

@Data
public class Employee {
    private Integer empId;
    private String empName;
    private Integer empGroupId;
    private Integer empLevel;
}

@Data
public class EmpLevels {
    private List<Employee> employees;
}

@Data
public class EmpTree {
    private Integer empId;
    private String empName;
    private Integer empLevel;
    private List<Employee> children;
}

My main method contains below stuff so far, regarding reading JSON and mapping employees,

EmpLevels empLevels = mapper.readValue(Paths.get("emp.json").toFile(), EmpLevels.class);
List<Employee> employees = empLevels.getEmployees();
System.out.println("Employees : " employees);

How to go ahead with building the logic to generate the JSON tree structure? Do we have any libraries that can help here? Or any latest Java release feature that can help generate this one?

CodePudding user response:

When I look at your JSON, what first comes to my mind would be:

    public class Employee {
    private Integer empId;
    private String empName;
    private Integer empGroupId;
    private List<Employee> children;
    }

If thats not it, maybe their is a way to generate an Object from your JSON with Jackson/ObjectMapper and find an idea their? But I don't know if Jackson can do this without a given class, but maybe it helps you while looking for a solution.

CodePudding user response:

It is a matter of algorithm. Libraries or Java feature can't help you.

First of all, EmpTree.children should be type of List<EmpTree>.

@Data
public class EmpTree {
    private Integer empId;
    private String empName;
    private Integer empLevel;
    private List<EmpTree> children;
}

Here is a recursive function that build a EmpTree.

public EmpTree buildTree(List<Employee> employees, int empId, int empLevel) {
    List<Employee> parent = employees.stream()
        .filter(employee -> empId == employee.getEmpId())
        .collect(Collectors.toList());
    List<Integer> groups = parent.stream()
        .map(Employee::getEmpGroupId)
        .collect(Collectors.toList());
    List<EmpTree> childTree = employees.stream()
        .filter(child -> child.getEmpLevel() == empLevel   1 && groups.contains(child.getEmpGroupId()))
        .map(Employee::getEmpId)
        .distinct()
        .map(childEmpId -> buildTree(employees, childEmpId, empLevel   1))
        .collect(Collectors.toList());
    return new EmpTree(empId, parent.get(0).getEmpName(), parent.get(0).getEmpLevel(), childTree.isEmpty() ? null : childTree);
}

Use this statement to call the function.

EmpTree root = buildTree(employees, 1, 0);
  • Related