In one JSON object one field has same value but rest of fields has different values , need same value as common rest of values as list of items

I am grouping the list of items by resource name, I am getting output like below i.e in every JSON object resourceName is the same, and other field values are different, but I need that resource name should come as common value and rest of the come as list of values.

{"groupedResourceDtos": {
    "Resource PopCheck": {
        "9": [{
            "id": 9,
            "resourceName": "Resource PopCheck",
            "groupedMonths": {
                "id": 9,
                "monthName": "Aug",
                "noOfLicenses": 8
            }
        }],
        "10": [{
            "id": 10,
            "resourceName": "Resource PopCheck",
            "groupedMonths": {
                "id": 10,
                "monthName": "Sep",
                "noOfLicenses": 11
            }
        }],
        "11": [{
            "id": 11,
            "resourceName": "Resource PopCheck",
            "groupedMonths": {
                "id": 11,
                "monthName": "Oct",
                "noOfLicenses": 7
            }
        }]
    }
}    

but I am expecting like

{"groupedResourceDtos": {
    "resourceName":  "Resource PopCheck",
    "groupedMonths": [{
        "id": 9,
        "monthName": "Aug",
        "noOfLicenses": 8
    },{
        "id": 10,
        "monthName": "Sep",
        "noOfLicenses": 11
    },{
        "id": 11,
        "monthName": "Oct",
        "noOfLicenses": 7
    }]
}}

Please help me with this

Answer

First, the DTO classes need to be defined for the mentioned JSON. This can be done as follows (using Lombok annotations):

@Data
static class Dto {
    private Map<String, Map<String, List<MyResource>>> groupedResourceDtos;
}

@Data
static class MyResource {
    int id;
    String resourceName;
    GroupedMonth groupedMonths;
}

@Data
static class GroupedMonth {
    int id;
    String monthName;
    int noOfLicenses;
}

Then the DTO for expected output should look like this:

@Data
@AllArgsConstructor
static class Remap {
    private String resourceName;
    private List<GroupedMonth> groupedMonths;
}

Assuming that there is a valid instance of Dto class parsed from the input JSON using Jackson ObjectMapper, the remapped instance can be created using Stream::flatMap and Stream::map operations applied to the contents of the the maps:

String json = "{...};" // large input JSON 

ObjectMapper mapper = new ObjectMapper();

Dto dto = mapper.readValue(json, Dto.class);

Remap remap = dto.groupedResourceDtos.entrySet()
   .stream()
   .map(e -> new Remap(
        e.getKey(), // resourceName
        (e.getValue().values()      // Collection<List<MyResource>>
            .stream()               // Stream<List<MyResource>>
            .flatMap(List::stream)  // Stream<MyResource>
            .map(MyResource::getGroupedMonths) // Stream<GroupedMonth>
            .collect(Collectors.toList())
        ) // List<GroupedMonth>
   ))
   .findFirst() // Optional<Remap>, dealing with only 1 value
   .orElseThrow(IllegalArgumentException::new);

Then remap value may be serialized to JSON:

System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(remap));

Output:

{
  "resourceName" : "Resource PopCheck",
  "groupedMonths" : [ {
    "id" : 9,
    "monthName" : "Aug",
    "noOfLicenses" : 8
  }, {
    "id" : 10,
    "monthName" : "Sep",
    "noOfLicenses" : 11
  }, {
    "id" : 11,
    "monthName" : "Oct",
    "noOfLicenses" : 7
  } ]
}