Home > Software engineering >  Jackson ObjectMapper Not Reading Inner Objects
Jackson ObjectMapper Not Reading Inner Objects

Time:03-30

I have a JSON file

{
    "readServiceAuthorizationResponse": {
        "serviceAuthorization": {
            "serviceAuthorizationId": "50043~220106065198",
            "status": "Approved",
            "receivedDate": "2022-1-6 1:21:12 PM",
            "providerFirstName": "Ranga",
            "providerLastName": "Thalluri",
            "organizationName": "General Hospital",
            "serviceLines": [{
                "statusReason": "Approved",
                "procedureDescription": "Room & board ward general classification",
                "requestedQuantity": "1.00",
                "approvedQuantity": "1.00",
                "deniedQuantity": "",
                "quantityUnitOfMeasure": "Day(s)",
                "providers": [{
                    "providerFirstName": "Ranga",
                    "providerLastName": "Thalluri",
                    "organizationName": ""
                }]
            }]
        }
    }
}

My Java to read this into an object is this:

package com.shawn.dto;

import java.nio.file.Files;
import java.nio.file.Paths;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.ObjectMapper;

@JsonIgnoreProperties(ignoreUnknown = true)
public class ServiceAuthorizationDTO {
    public String serviceAuthorizationId;
    public String status;
    public String receivedDate;
    public String providerFirstName;
    public String providerLastName;
    public String organizationName;
    public ServiceLine[] serviceLines;
    
    public static ServiceAuthorizationDTO create(String json) {
        ObjectMapper m = new ObjectMapper();
        try {
            Outer outer = m.readValue(json, Outer.class);
            return outer.readServiceAuthorizationResponse.serviceAuthorization;
        } catch (Exception e) {
            return null;
        }
    }
    
    @JsonIgnoreProperties(ignoreUnknown = true)
    static class ReadServiceAuthorizationResponse {
        public ServiceAuthorizationDTO serviceAuthorization;        

    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    static class Outer {
        public ReadServiceAuthorizationResponse readServiceAuthorizationResponse;       
        
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class ServiceLine {
        String statusReason;
        String procedureDescription;
        String requestedQuantity;
        String approvedQuantity;
        String deniedQuantity;
        String quantityUnitOfMeasure;
        Provider[] providers;
        
    }
    
    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class Provider {
        String providerFirstName;
        String providerLastName;
        String organizationName;

    }
    
    public static void main(String[] args) {
        try {
            String json = new String(Files.readAllBytes(Paths.get("c:/temp/test.json")));
            ServiceAuthorizationDTO dao = ServiceAuthorizationDTO.create(json);
            System.out.println("serviceAuthorizationId: "   dao.serviceAuthorizationId);
            System.out.println("serviceLines[0].procedureDescription: "   dao.serviceLines[0].procedureDescription);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
    
}

When I run it I get this:

serviceAuthorizationId: 50043~220106065198
serviceLines[0].procedureDescription: null

The outer fields in the object like providerId are read from the JSON. But the serviceLines array shows 1 element, and all fields in that class are empty.

Any ideas? This is the first time I've used real objects with JSON. I've always mapped it into Map objects and pulled the fields out manually. Thanks.

CodePudding user response:

Fields in classes ServiceLine and Provider have package-private access modifiers. Jackson can't deserialize into private fields with its default settings. Because it needs getter or setter methods.

Solution 1: Make fields public

    public static class ServiceLine {
        public String statusReason;
        public String procedureDescription;
        public String requestedQuantity;
        public String approvedQuantity;
        public String deniedQuantity;
        public String quantityUnitOfMeasure;
        public Provider[] providers;        
    }

Solution 2: Use @JsonAutoDetect annotation

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
public class ServiceLine {
    String statusReason;
    String procedureDescription;
    String requestedQuantity;
    String approvedQuantity;
    String deniedQuantity;
    String quantityUnitOfMeasure;
    Provider[] providers;
}

Solution 3: Change visibility on the ObjectMapper (doc)

    public static ServiceAuthorizationDTO create(String json) {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
            Outer outer = objectMapper.readValue(json, Outer.class);
            return outer.readServiceAuthorizationResponse.serviceAuthorization;
        } catch (Exception e) {
            return null;
        }
    }
  • Related