Skip to content
Advertisement

Convert a List of JSON-objects input into a nested Map

I have a String input in the following format:

Input String: [{ "id":"1", "name":"A", "address":"St 1"},{ "id":"2", "name":"B", "address":"St 2"}, ...]

And I want to be able to convert this to a Map<String, Map<String, String>> format. So, something like:

Required Output Format: {1: {id:1, name:"A", address: "St 1"} 2: {id:2, name:"B", address: "St 2"}}

I created a class to help in parsing the input:

public class Student{
  private String id;
  private String name;
  private String address;
}

Which I am trying to do through Jackson’s ObjectMapper to get the data in the format: List<Student> format and then use Collectors.toMap() to convert it to a Map of Maps format.

All the examples I have seen so far suggest an approach like:

List<Student> student = objectMapper.readValue(inputString, new TypeReference<List<Student>>(){});

Map<String, Student> studentTempMap = student.stream()
    .collect(Collectors.toMap(
        Student::getId,
        Function.identity()
    ));

Which makes the studentTempMap something like:

{ 1: object of Student("id":"1", "name":"A", "address":"St 1"),
  2: object of Student("id":"2", "name":"B", "address":"St 2"), 
  ... }

A brute force approach from here:

  1. create a new Map studentMap
  2. Iterate over keys (which are “id”) in studentTempMap.
    • Then create another Map, temp.
    • Add keys “id”, “name”, and “address” and values using something like studentTempMap.get(2).get("id"), and something similar for all the other keys (name and address). Where 2 would be the current iterator key over the Map studentTempMap.
    • Finally add a key say as 2 (current iterator) and value temp in the studentMap.

I do not want to use this brute force approach as I have a large number of Student objects.

Is there a way through ObjectMapper to get the output directly in the form of Map<String, Map<String, String>> format? Or is there a way through Collectors.toMap to parse it to the above format?

Advertisement

Answer

I want to be able to convert this to a Map<String, Map<String, String>>

If you want to obtain a nested map of strings Map<String,Map<String,String>> as a result, you don’t need to convert JSON into a list of POJO.

Instead, you can parse JSON into a list of maps List<Map<String,String>> and then generate a nested map.

String inputString = """
    [{ "id":"1", "name":"A", "address":"St 1"},
     { "id":"2", "name":"B", "address":"St 2"}]""";
    
ObjectMapper objectMapper = new ObjectMapper();
List<Map<String, String>> students = objectMapper.readValue(
    inputString, new TypeReference<>() {}
);
        
Map<String, Map<String, String>> studentMapById = students.stream()
    .collect(Collectors.toMap(
        map -> map.get("id"), // key 
        Function.identity(),  // value
        (left, right) -> left // resolving duplicates
    ));
    
studentMapById.forEach((k, v) -> System.out.println(k + " : " + v));

Output:

1 : {id=1, name=A, address=St 1}
2 : {id=2, name=B, address=St 2}
Advertisement