5

I have a service from where I get a json string response like as shown below

{
  "id": "123",
  "name": "John"
}

I consume the rest call using HttpClient and converts the json string to Map<String, String> like as shown below.

String url= "http://www.mocky.io/v2/5979c2f5110000f4029edc93";
HttpClient client = HttpClientBuilder.create().build();
HttpGet httpGet = new HttpGet(url);
httpGet.setHeader("Content-Type", "application/json");
HttpResponse httpresponse = client.execute(httpGet);
String response = EntityUtils.toString(httpresponse.getEntity());

ObjectMapper mapper = new ObjectMapper();
Map<String, String> map = mapper.readValue(response, new TypeReference<Map<String, String>>(){});

The conversion from json string to HashMap is working fine, but actually my requirement was sometimes there can be some nested json within the main json, for example in the below json I am having an additional address key which is again a nested json having city and town details.

{
  "id": "123",
  "name": "John",
  "address": {
    "city": "Chennai",
    "town": "Guindy"
  }
}

If any nested json comes I need the make the json like as shown below

{
  "id": "123",
  "name": "John",
  "address.city": "Chennai",
  "address.town": "Guindy"
}

Currently I am using jackson library, but open to any other library which will give me this feature out of box

Can anyone help me by giving some suggestion on this.

Alex Man
  • 4,746
  • 17
  • 93
  • 178

1 Answers1

4

Here is a recursive method that will flatten a nested Map with any depth to the desired dot notation. You can pass it to Jackson's ObjectMapper to get the desired json output:

@SuppressWarnings("unchecked")
public static Map<String, String> flatMap(String parentKey, Map<String, Object> nestedMap)
{
    Map<String, String> flatMap = new HashMap<>();
    String prefixKey = parentKey != null ? parentKey + "." : "";
    for (Map.Entry<String, Object> entry : nestedMap.entrySet()) {
        if (entry.getValue() instanceof String) {
            flatMap.put(prefixKey + entry.getKey(), (String)entry.getValue());
        }
        if (entry.getValue() instanceof Map) {
            flatMap.putAll(flatMap(prefixKey + entry.getKey(), (Map<String, Object>)entry.getValue()));
        }
    }
    return flatMap;
}

Usage:

mapper.writeValue(System.out, flatMap(null, nestedMap));
Sharon Ben Asher
  • 13,849
  • 5
  • 33
  • 47
  • 1
    @SharaonBenAsher Thanks for the answer, do we have this feature in any library out of the box – Alex Man Jul 27 '17 at 12:29
  • but how I will identify the nested json within the main json......should I iterate the main json and check for nested json.....Can you give me an example – Alex Man Jul 27 '17 at 13:04
  • you dont need to identify nested json. you load the nested json into a Map, flatten it using the above method and you can serialize it to get desired json – Sharon Ben Asher Jul 27 '17 at 13:16
  • what will I do if I am getting the response as array of objects – Alex Man Jul 27 '17 at 13:45
  • then you adopt the code to this situation. I have given you an example. how hard is it to change the code to handle new situations? – Sharon Ben Asher Jul 27 '17 at 13:48
  • what is meant is something like this http://www.mocky.io/v2/5979f04f110000a5049edd6e – Alex Man Jul 27 '17 at 14:15