-2

I've a

Map<String, Object> response = {
    sendResponse = {
        return = {
            SendResponse = {
                txnID = 4fa160ce-638f-4556-9313-afbef543fadd,
                emailTypeID = 1020261131,
                txnStatusCode = 1,
                txnStatusMessage = OK,
                status = [
                    {   CommunicationStatus = {
                            type = EMAIL,
                            statusCode = 1,
                            statusMessage = OK
                        }
                    }
                ]
            }
        }
    }
}

How to extract "statusMessage" from response Map. Please advise.

The runtime types of nested objects are LinkedHashMap<K,V> and Type of the Status is ArrayList which has LinkedHashMap<K,V> inside.

I tried using get() method for example like below but I'm facing casting warnings. Ex: response.get("sendResponse")).get("return")).get("SendResponse").get("status").get(0).get("CommunicationStatus").get(statusMessage);

MyUser12
  • 13
  • 3
  • Welcome to Stack Overflow. After the downvotes you may want to read [How do I ask a good question?](https://stackoverflow.com/help/how-to-ask) (once more) and see if you can improve your question accordingly. – Ole V.V. Aug 26 '20 at 04:43
  • Hi, The runtime types of nested objects are LinkedHashMap and Type of the Status is ArrayList which has LinkedHashMap inside and we are using Jackson library – MyUser12 Aug 26 '20 at 04:47
  • Thanks for providing more information, it’s helpful. It’s also best to do it as edits to the question. You have got an edit link under the question. Only this time I edited for you. Next time will be your turn. :-) – Ole V.V. Aug 26 '20 at 04:50

1 Answers1

0

It takes a bit alright.

    Map<String, Object> response = new LinkedHashMap<>(Map.of(
            "sendResponse", new LinkedHashMap<>(Map.of(
                    "return", new LinkedHashMap<>(Map.of(
                            "SendResponse", new LinkedHashMap<>(Map.of(
                                    "txnId", "4fa160ce-638f-4556-9313-afbef543fadd",
                                    "status", new ArrayList<Object>(List.of(
                                            new LinkedHashMap<>(Map.of(
                                                    "CommunicationStatus", new LinkedHashMap<String, Object>(Map.of(
                                                            "type", "EMAIL",
                                                            "statusMessage", "OK"))))))))))))));
    
    System.out.println(response);
    
    Map<?, ?> sendResponse = (Map<?, ?>) response.get("sendResponse");
    Map<?, ?> returnMap = (Map<?, ?>) sendResponse.get("return");
    Map<?, ?> sendResponseCapitalS = (Map<?, ?>) returnMap.get("SendResponse");
    List<?> status = (List<?>) sendResponseCapitalS.get("status");
    Optional<Map<?, ?>> statusEmail = (Optional<Map<?, ?>>) status.stream()
            .map(m -> ((Map<?, ?>) m).get("CommunicationStatus"))
            .filter(m -> ((Map<?, ?>) m).get("type").equals("EMAIL"))
            .findAny();
    Optional<Object> statusMessage = statusEmail.map(m -> m.get("statusMessage"));
    
    statusMessage.ifPresent(System.out::println);

I have left out some uninteresting bits from your map, it should make no difference. I am printing the map I have constructed for you to check that it looks like yours (only with a few bits left out). Output from the above snippet is:

{sendResponse={return={SendResponse={txnId=4fa160ce-638f-4556-9313-afbef543fadd,status=[{CommunicationStatus={statusMessage=OK, type=EMAIL}}]}}}}
OK

I am using a stream operation to take out the map from the list where type is EMAIL. Please check whether this is correct for your requirements.

Edit: You and I have both observed the warning Type safety: Unchecked cast from Optional<capture#16-of ?> to Optional<Map>. I found no good way of getting rid of it. The following variant of the last two lines before the final printout do not show the warning:

    Optional<?> statusEmail = status.stream()
            .map(m -> ((Map<?, ?>) m).get("CommunicationStatus"))
            .filter(m -> ((Map<?, ?>) m).get("type").equals("EMAIL"))
            .findAny();
    Optional<Object> statusMessage = statusEmail.map(m -> ((Map<?, ?>) m).get("statusMessage"));

However, they give less information about the type of statusEmail, which I find a clear disadvantage, which is why I opted for posting the first variant above in spite of the warning.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • I'm seeing a typesafety warning (Type safety: Unchecked cast from Optional to Optional>) at this place - Optional> statusEmail = (Optional>) status.stream() .map(m -> ((Map, ?>) m).get("CommunicationStatus")) .filter(m -> ((Map, ?>) m).get("type").equals("EMAIL")) .findAny(); – MyUser12 Aug 26 '20 at 13:23
  • Thank you for your time. Is it appropriate to use casting Map, ?> like this? – MyUser12 Aug 26 '20 at 13:24
  • For the type safety warning see my edit. For the cast to `Map, ?>`, it’s a matter of taste. I can’t see we can do without a cast. You may cast to for example `LinkedHashMap` if you prefer. It doesn’t make much of a difference IMHO. – Ole V.V. Aug 27 '20 at 01:41