Jeeppp
Jeeppp

Reputation: 1573

Create a nested map from Json using streams

I have the below Json that I'm reading into nested POJOs with the same structure.

{
  "employees": [
    {
      "name": "John",
      "age": "30",
      "proData": [
        {
          "year": "1",
          "idList": [
            "234342",
            "532542",
            "325424",
            "234234"
          ]
        },
        {
          "year": "2",
          "idList": [
            "234342",
            "532542",
            "325424",
            "234234"
          ]
        },
        {
          "year": "3",
          "idList": [
            "234342",
            "532542",
            "325424",
            "234234"
          ]
        }
      ]
    },
    {
      "name": "Scott",
      "age": "32",
      "proData": [
        {
          "year": "1",
          "idList": [
            "234342",
            "532542",
            "325424",
            "234234"
          ]
        },
        {
          "year": "2",
          "idList": [
            "234342",
            "532542",
            "325424",
            "234234"
          ]
        },
        {
          "year": "3",
          "idList": [
            "234342",
            "532542",
            "325424",
            "234234"
          ]
        }
      ]
    }
  ]
}

Now I wanted to map this to a structure like below, the ProData can be initialized using each of the string in the idList.

Map<String,Map<String,List<ProData>>> finalMap

I have written something like the below and it works.

        Map<String,Map<String,List<ProData>>> finalMap = new HashMap<>();

        for(Employee employee:root.getEmployees()){
            Map<String,List<ProData>> proDataMap = new HashMap<>();
            for(ProData proData: employee.getProData()){
                List<ProData> finalObjs = new ArrayList<>();
                for(String id:proData.getIdList()){
                   finalObjs.add(new ProData(id));
                }

                proDataMap.put(proData.getYear(),finalObjs);
            }
            finalMap.put(employee.getName(),proDataMap);
        }

I wanted to make a better version using the stream API.

Upvotes: 2

Views: 496

Answers (2)

Hard Worker
Hard Worker

Reputation: 1121

should be something similar to,

root.stream().forEach(employee -> {
                Map<String,List<ProData>> proDataMap = new HashMap<>();
                employee.getProdData().stream().forEach(data -> {
                    List<ProData> finalObjs = new ArrayList<>();
                    data.getIdList().stream().forEach(data -> {
                        finalObjs.add(new ProData(id));
                    });
                });
            });

but regardless you can also use Gson to parse it https://mkyong.com/java/how-to-parse-json-with-gson/

Upvotes: 0

Sweeper
Sweeper

Reputation: 274480

The end result is a map, so use the toMap collector. The maps' keys are the employee names (assuming no duplicates), and the map values require a little bit more work.

root.getEmployees().stream().collect(
    Collectors.toMap(
        Employee::getName,
        Employee::getProDataMap
    )
}

Now let's try writing getProDataMap in Employee. Again we use the toMap collector. The keys are the years (assuming no duplicates), and the values are the id lists mapped to ProData using the constructor.

public Map<String, List<ProData>> getProDataMap() {
    return this.getProData().stream().collect(
        Collectors.toMap(
            ProData::getYear,
            proData -> proData.getIdList().stream()
                .map(ProData::new)
                .collect(Collectors.toList())
        )
    )
}

Upvotes: 2

Related Questions