Home > Blockchain >  How to convert HashMap value to Java Pojo?
How to convert HashMap value to Java Pojo?

Time:12-19

I am working on consuming external API in spring boot application. I have written my JSON response that is coming from external API using RestTemplate and exchange() method of HttpEntity.

Below is the response:

String json = """
            {
                "links": {
                    "RCDSO - Production Environment Cost": {
                        "href": "href 1"
                    },
                    "RCDSO - Development & UAT Environment Cost": {
                        "href": "href 2"
                    },
                    "RCDSO - Total Cost for Prod - Compugen Managed": {
                        "href": "href 3"
                    },
                    "RCDSO - Virtual Machine Cost": {
                        "href": "href 4"
                    },
                    "RCDSO - Azure File Storage Cost": {
                        "href": "href 5"
                    },
                    "RCDSO - Azure Backup and Site Recovery": {
                        "href": "href 6"
                    },
                    "RCDSO - Azure App Services Cost": {
                        "href": "href 7"
                    }
                }
            }
            """;
    Map<String, Map<String, String>> links = JsonPath.read(json, "$.links");
    links.forEach((key, value) -> {
        System.out.println("k = "   key);
        System.out.print("v = ");
        value.forEach((key2, value2) -> {
            System.out.println("key = "   key2   " : value = "   value2);
        });
    });

In above code, I tried to get values from Map. Now I want to convert into my POJO class.

Below is my Pojo named OlapCustomReportResponse.java:

public class OlapCustomReportResponse {
        private String name;
        private String href;
}

I extracted key from outer loop and on the basis of key I extracted value from inner loop as below:

Key 1 = RCDSO - Production Environment Cost
Key 2 = href : Value 2 = some url related to key 1

Key 2 = RCDSO - Development & UAT Environment Cost
Key 2 = href : Value 2 = some url related to key 2 

Key 3 = RCDSO - Total Cost for Prod - Compugen Managed
Key 2 = href : Value 2 = some url related to key 3

Key 4 = RCDSO - Virtual Machine Cost
Key 2 = href : Value 2 = some url related to key 4 

.... and so on

I want my OlapCustomReportResponse.java should look something like below:

    [
      {
        "href" : "some url of key 1",
        "name" : "key 1"
      },
      { 
        "href" : "some url of key 2",
        "name" : "key 2"
      },
      { 
        "href" : "some url of key 3",
        "name" : "key 3"
      },
      { 
        "href" : "some url of key 4",
        "name" : "key 4"
      }
        ...... and so on...
   ]

So my main motive is to map or convert that result to my POJO class. How should I do or what would be the possible approach?

CodePudding user response:

I am actually using com.fasterxml.jackson.databind.ObjectMapper and it is really fast, strong and a good json parser

ObjectMapper objectMapper = new ObjectMapper();

TypeReference<HashMap<String, Map<String, String>>> typeRef = new TypeReference<HashMap<String, Map<String, String>>>() {};

Map<String, Map<String, String>> results = objectMapper.readValue(file, typeRef);

CodePudding user response:

With the few given:

Map<String, Map<String, String>> links = // from somewhere

and (e.g) constructor:

public OlapCustomReportResponse(String name, String href) {
  this.name = name;
  this.href = href;
}

, we could just (do the transformation with streaming api):

List<OlapCustomReportResponse> result = new ArrayList<>(); // alternatively: Set(?)
links.forEach((key, value) -> {
  result.add(new OlapCustomReportResponse(
    key, value.get("href")
  ));
});

Test:

// import static org.assertj.core.api.Assertions.assertThat;
// import static org.junit.jupiter.api.Assertions.*;
...
assertNotNull(result);
assertThat(result).isNotEmpty();
result.forEach(
  (ocrr) -> { 
    assertNotNull(ocrr); // not null
    assertThat(ocrr.getName()).isNotBlank(); // according to test data
    assertThat(ocrr.getHref()).isNotBlank(); // ...
    assertTrue(links.containsKey(ocrr.getName())); // result(x) -> links(x):
    assertEquals(links.get(ocrr.getName()).get("href"), ocrr.getHref()); // result(x).getHref() -> links(x).get("href")
  }
);
// links(x) <- result(x):
assertEquals(links.size(), result.size());

Alternative approaches:

  • links.entrySet().stream().collect(...) (with identic code, "combination"(!?)):
    List<OlapCustomReportResponse> result = links.entrySet().stream().collect(
         ArrayList::new, // <- supplier
         (list, entry) -> { // <- accumulator
           list.add(
               new OlapCustomReportResponse(
                   entry.getKey(), entry.getValue().get("href")
               )
           );
         },
         (first, second) -> { // <- combiner (for more complex use cases)
           first.addAll(second);
         }
    );
    
  • traditional loop...

Assumptions:

  • receiving response (format) from external api.
  • forwarding of (internal) result via default(jackson)/custom http converters.
  • With
    // import com.fasterxml.jackson.databind.ObjectMapper;
    ObjectMapper om = new ObjectMapper();// or @Autowired from spring context ;)
    om.writeValue(System.err, result);
    
    to mimic(/use) "spring defaults" on (e.g.):
    @ResponseBody List<OlapCustomReportResponse> serveSome(// ...
    
    prints (unformatted/according to your spring.jackson.*/context OM settings):
    [
       {"name":"RCDSO - Production Environment Cost","href":"href 1"}, 
       {"name":"RCDSO - Development & UAT Environment Cost","href":"href 2"},
       {"name":"RCDSO - Total Cost for Prod - Compugen Managed","href":"href 3"},
       {"name":"RCDSO - Virtual Machine Cost","href":"href 4"}, 
       {"name":"RCDSO - Azure File Storage Cost","href":"href 5"}, 
       {"name":"RCDSO - Azure Backup and Site Recovery","href":"href 6"}, 
       {"name":"RCDSO - Azure App Services Cost","href":"href 7"}
    ]
    

Problems:

  • (Only) when links or value (for any value in likns.getValues()) is null!
  • Related