Search code examples
javajacksonpojoobjectmapper

jackson mapping nested hashmap to nested pojo class in java


I have a nested java map like this inputMap: {jobId={EndpointReference={ReferenceParameters={ResourceURI=http://schemas.com/wbem/wscim/1/cim-schema/2/Job, SelectorSet={Selector=[JID_502260561923, root/im]}}, Address=http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous}}, returncode=4096, messageId=null, arguments=null, message=null} which I want to map to java pojo and here is my pojo classes.

@Getter
@Setter
@ToString
public class DMResponseMapper {
    @Getter
    @Setter
    @ToString
    public static class GetSysConfigDMResponseMapper {
        @JsonProperty("jobId")
        private EndpointReferenceMapper endpointReferenceMapper;
        private Integer returnCode;
        private String messageId;
        private String arguments;
        private String message;

        @Getter
        @Setter
        @ToString
        public static class EndpointReferenceMapper {
            @JsonProperty("ReferenceParameters")
            private ReferenceParametersMapper referenceParametersMapper;
            @JsonProperty("Address")
            private String address;

                @Getter
                @Setter
                @ToString
                public static class ReferenceParametersMapper {

                    @JsonProperty("ResourceURI")
                    private String resourceURI;

                    @JsonProperty("SelectorSet")
                    private SelectorSetMapper selectorSetMapper;

                    @Getter
                    @Setter
                    @ToString
                    public static class SelectorSetMapper {

                        @JsonProperty("Selector")
                        private List<String> selector;
                    }
                }
            }
        }
    }

but objectMapper.convertValue(inputMap, GetSysConfigDMResponseMapper.class) is NOT mapping the nested classes.. just the top level fields. My objectMapper is instantiated like this:

static {
objectMapper = new ObjectMapper();
objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

}

Response Object is :

DMResponseMapper.GetSysConfigDMResponseMapper(endpointReferenceMapper=DMResponseMapper.GetSysConfigDMResponseMapper.EndpointReferenceMapper(referenceParametersMapper=null, address=null), returnCode=4096, messageId=null, arguments=null, message=null)

Can anyone please suggest, what is wrong here?

Upon debugging this is what I see: Converted endpointReferenceMapper to type Object.

DMResponseMapper.GetSysConfigDMResponseMapper(endpointReferenceMapper={EndpointReference={ReferenceParameters={ResourceURI=http://schemas.com/wbem/wscim/1/cim-schema/2/Job, SelectorSet={Selector=[JID_502318722705, root/dcim]}}, Address=http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous}}, returnCode=4096, messageId=null, arguments=null, message=null)

Solution

  • The DMResponseMapper pojo needs to follow the structure of your source data more closely.

    Your source Map object has the following structure, based on the info in the question:

    inputMap: 
    {
      jobId={
        EndpointReference={
          ReferenceParameters={
            ResourceURI=http://schemas.com/wbem/wscim/1/cim-schema/2/Job, 
            SelectorSet={
              Selector=[JID_502260561923, root/im]
            }
          }, 
          Address=http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous
        }
      }, 
      returncode=4096, 
      messageId=null, 
      arguments=null, 
      message=null
    }
    

    So, I adapted your DMResponseMapper pojo class to more closely map to that structure - and I changed the nested class names as well. Here is a summary of the nested classes with their fields for your data:

    //
    // NOT the actual class - just an overview of the structure!
    //
    class DMResponseMapper {
    
        private JobId jobId;
        private Integer returncode;
        private Object messageId;
        private Object arguments;
        private Object message;
    
        class JobId {
    
            private EndpointReference endpointReference;
    
            class EndpointReference {
    
                private ReferenceParameters referenceParameters;
                private String address;
    
                class ReferenceParameters {
    
                    private String resourceURI;
                    private SelectorSet selectorSet;
    
                    class SelectorSet {
                        private List<String> selector = null;
                    }
                }
            }
        }
    }
    

    This gave me the following, when fleshed out with annotations and getters/setters:

    //
    // Here is the actual class, based on the above structure.
    //
    import com.fasterxml.jackson.annotation.JsonProperty;
    import java.util.List;
    
    public class DMResponseMapper {
    
        @JsonProperty("jobId")
        private JobId jobId;
        @JsonProperty("returncode")
        private Integer returncode;
        @JsonProperty("messageId")
        private Object messageId;
        @JsonProperty("arguments")
        private Object arguments;
        @JsonProperty("message")
        private Object message;
    
        @JsonProperty("jobId")
        public JobId getJobId() {
            return jobId;
        }
    
        @JsonProperty("jobId")
        public void setJobId(JobId jobId) {
            this.jobId = jobId;
        }
    
        @JsonProperty("returncode")
        public Integer getReturncode() {
            return returncode;
        }
    
        @JsonProperty("returncode")
        public void setReturncode(Integer returncode) {
            this.returncode = returncode;
        }
    
        @JsonProperty("messageId")
        public Object getMessageId() {
            return messageId;
        }
    
        @JsonProperty("messageId")
        public void setMessageId(Object messageId) {
            this.messageId = messageId;
        }
    
        @JsonProperty("arguments")
        public Object getArguments() {
            return arguments;
        }
    
        @JsonProperty("arguments")
        public void setArguments(Object arguments) {
            this.arguments = arguments;
        }
    
        @JsonProperty("message")
        public Object getMessage() {
            return message;
        }
    
        @JsonProperty("message")
        public void setMessage(Object message) {
            this.message = message;
        }
    
        public static class JobId {
    
            @JsonProperty("EndpointReference")
            private EndpointReference endpointReference;
    
            @JsonProperty("EndpointReference")
            public EndpointReference getEndpointReference() {
                return endpointReference;
            }
    
            @JsonProperty("EndpointReference")
            public void setEndpointReference(EndpointReference endpointReference) {
                this.endpointReference = endpointReference;
            }
    
            public static class EndpointReference {
    
                @JsonProperty("ReferenceParameters")
                private ReferenceParameters referenceParameters;
                @JsonProperty("Address")
                private String address;
    
                @JsonProperty("ReferenceParameters")
                public ReferenceParameters getReferenceParameters() {
                    return referenceParameters;
                }
    
                @JsonProperty("ReferenceParameters")
                public void setReferenceParameters(ReferenceParameters referenceParameters) {
                    this.referenceParameters = referenceParameters;
                }
    
                @JsonProperty("Address")
                public String getAddress() {
                    return address;
                }
    
                @JsonProperty("Address")
                public void setAddress(String address) {
                    this.address = address;
                }
    
                public static class ReferenceParameters {
    
                    @JsonProperty("ResourceURI")
                    private String resourceURI;
                    @JsonProperty("SelectorSet")
                    private SelectorSet selectorSet;
    
                    @JsonProperty("ResourceURI")
                    public String getResourceURI() {
                        return resourceURI;
                    }
    
                    @JsonProperty("ResourceURI")
                    public void setResourceURI(String resourceURI) {
                        this.resourceURI = resourceURI;
                    }
    
                    @JsonProperty("SelectorSet")
                    public SelectorSet getSelectorSet() {
                        return selectorSet;
                    }
    
                    @JsonProperty("SelectorSet")
                    public void setSelectorSet(SelectorSet selectorSet) {
                        this.selectorSet = selectorSet;
                    }
    
                    public static class SelectorSet {
    
                        @JsonProperty("Selector")
                        private List<String> selector = null;
    
                        @JsonProperty("Selector")
                        public List<String> getSelector() {
                            return selector;
                        }
    
                        @JsonProperty("Selector")
                        public void setSelector(List<String> selector) {
                            this.selector = selector;
                        }
    
                    }
    
                }
    
            }
    
        }
    
    }
    

    This is invoked as follows:

    First, some test data:

    List<String> selector = new ArrayList();
    selector.add("JID_502260561923");
    selector.add("root/im");
    
    Map<String, Object> selectorSet = new HashMap();
    selectorSet.put("Selector", selector);
    
    String resourceURI = "http://schemas.com/wbem/wscim/1/cim-schema/2/Job";
    
    Map<String, Object> referenceParameters = new HashMap();
    referenceParameters.put("ResourceURI", resourceURI);
    referenceParameters.put("SelectorSet", selectorSet);
    
    String address = "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous";
    
    Map<String, Object> endpointReference = new HashMap();
    endpointReference.put("ReferenceParameters", referenceParameters);
    endpointReference.put("Address", address);
    
    Map<String, Object> jobId = new HashMap();
    jobId.put("EndpointReference", endpointReference);
    
    Map<String, Object> inputMap = new HashMap();
    inputMap.put("jobId", jobId);
    inputMap.put("returncode", 4096);
    inputMap.put("messageId", "foo");
    inputMap.put("arguments", "bar");
    inputMap.put("message", "baz");
    

    Note I replaced your null values with strings, for testing and demonstration.

    Then the code to perform the mapping:

    ObjectMapper objectMapper = new ObjectMapper();
    DMResponseMapper mapper = objectMapper.convertValue(inputMap, DMResponseMapper.class);
    

    The resulting mapper object contains the test data:

    enter image description here