1

So I'm working on a REST client that consumes a REST API to get a JSON object using the Spring RestTemplate. So I get an HTTP 200 OK response but the list (equipment) inside the class object is null. But other fields are fetched. When I do the same request using the Postman it works well. What might be the reason for this?

The RestTemplate code snippet :

 RestTemplate restTemplate = new RestTemplate();
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.add("Content-Type", "application/json");
requestHeaders.add("Authorization", "Bearer " + apiToken);
HttpEntity entity = new HttpEntity(requestHeaders);
ResponseEntity<CloverMerchant> response = restTemplate.exchange(getMerchantDetailsUrl, HttpMethod.GET, entity, CloverMerchant.class);
return response.getBody();

The CloverMerchant model class :

private String id;
private String name;
private String website;
private boolean isBillable;
private CloverBusinessEquipments equipment;

// other relevant getters and setters

The CloverBusinessEquipments model class:

private List<CloverBusinessEquipment> elements;

    public CloverBusinessEquipments() {
}

@JsonGetter("elements")
public List<CloverBusinessEquipment> getElements() {
    return elements;
}

The CloverBusinessEquipment model class :

private String merchantId;
private String serialNumber;
private String equipmentCode;
private String equipmentCodeDesc;
private String provisionedDeviceType;
private boolean boarded;
private boolean provisioned;

// relevant getters and setters

The expected response JSON from the REST API:

{
  "id": "5ZTFCGXQKVZNA",
  "name": "xxxx",
  "website": "https://xxxx.io",
  "isBillable": false,
  "equipment": {
  "elements": [
    {
        "merchantId": "5ZTFCGXQKVZNA",
        "boarded": false,
        "provisioned": true,
        "serialNumber": "C030UQ71040182",
        "equipmentCode": "105J",
        "equipmentCodeDesc": "Clover Mini",
        "provisionedDeviceType": "MAPLECUTTER"
    },
    {
        "merchantId": "5ZTFCGXQKVZNA",
        "boarded": false,
        "provisioned": true,
        "serialNumber": "C050UQ75150054",
        "equipmentCode": "1297",
        "equipmentCodeDesc": "Clover Station 2018",
        "provisionedDeviceType": "GOLDENOAK"
       }
    ]
  }
}
GeekySelene
  • 847
  • 3
  • 13
  • 31
  • is the list equipments or equipment? Your question doesn't match your code – Jacob Botuck Mar 08 '19 at 05:17
  • are you using jackson? if yes which version 1.x or 2.x ? – Vivek Mar 08 '19 at 07:12
  • @VibrantVivek sorry its because i updated the question later, i corrected it. Im using jackson 2.4.1 for data binding – GeekySelene Mar 08 '19 at 07:19
  • @JohnDoe921 please Try this : http://www.jsonschema2pojo.org ...paste your expected JSON and choose JSON as source and correct jackson version. And Generate the POJO...paste the exact in you code ...yeah you can rename back to Clover....etc etc....it should work , if not let us know here – Vivek Mar 08 '19 at 07:43
  • 1
    If you call `restTemplate.exchange(getMerchantDetailsUrl, HttpMethod.GET, entity, String.class)`, does the json string contains all expected equipment? – noiaverbale Mar 13 '19 at 07:10
  • Do you have any other annotations in your class aside this in the question? – Kamil W Mar 13 '19 at 07:14
  • @noiaverbale yes it contains the expected equipment – GeekySelene Mar 13 '19 at 07:16
  • @KamilW yes i have used "@JsonIgnoreProperties(ignoreUnknown = true)" to ignore deserialization issues for any property – GeekySelene Mar 13 '19 at 07:19
  • Try to play with `@JsonProperty`, `@JsonSetter` maybe it would help. – Kamil W Mar 13 '19 at 07:27
  • 1
    isn't it same as : https://stackoverflow.com/questions/55043467/having-null-response-for-a-list-inside-a-class-object-in-rest-api-call-with-rest#comment96865334_55043467 You didn't replied to my comment there...is there a reason you put same question again? – Vivek Mar 13 '19 at 08:26
  • Don't post duplicate questions. Edit your original question to include all the details. –  Mar 16 '19 at 15:35

2 Answers2

0

Your model does not represent the JSON response. You are trying to find the JSONObject with key "elements" at the root level of the JSON, but in reality it is at the second level after "equipment" key.

The variable - private CloverBusinessEquipments equipments; should represent this:

"equipment": {
    "elements": [
        {
            "merchantId": "5ZTFCGXQKVZNA",
            "boarded": false,
            "provisioned": true,
            "serialNumber": "C030UQ71040182",
            "equipmentCode": "105J",
            "equipmentCodeDesc": "Clover Mini",
            "provisionedDeviceType": "MAPLECUTTER"
        },
        {
            "merchantId": "5ZTFCGXQKVZNA",
            "boarded": false,
            "provisioned": true,
            "serialNumber": "C050UQ75150054",
            "equipmentCode": "1297",
            "equipmentCodeDesc": "Clover Station 2018",
            "provisionedDeviceType": "GOLDENOAK"
        }
    ]
}

But you have modelled your POJO which thinks that the equipments variable will be like below:

"elements": 
        {
            "merchantId": "5ZTFCGXQKVZNA",
            "boarded": false,
            "provisioned": true,
            "serialNumber": "C030UQ71040182",
            "equipmentCode": "105J",
            "equipmentCodeDesc": "Clover Mini",
            "provisionedDeviceType": "MAPLECUTTER"
        }
uneq95
  • 2,158
  • 2
  • 17
  • 28
0

You need to remodel your class as below and check

remove getter method
CloverMerchant.java

private String id;
private String name;
private String website;
@JsonProperty("isBillable")
private boolean isBillable;
private CloverBusinessEquipments equipment;

Update CloverBusinessEquipments with the following code.
CloverBusinessEquipments.java

private List<CloverBusinessEquipment> elements;

Create new PoJo class
CloverBusinessEquipment.java

private String merchantId;
private String serialNumber;
private String equipmentCode;
private String equipmentCodeDesc;
private String provisionedDeviceType;
private boolean boarded;
private boolean provisioned;

Main.java

ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
String str = "{\"id\":\"5ZTFCGXQKVZNA\",\"name\":\"xxxx\",\"website\":\"https://xxxx.io\",\"isBillable\":true,\"equipment\":{\"elements\":[{\"merchantId\":\"5ZTFCGXQKVZNA\",\"boarded\":false,\"provisioned\":true,\"serialNumber\":\"C030UQ71040182\",\"equipmentCode\":\"105J\",\"equipmentCodeDesc\":\"Clover Mini\",\"provisionedDeviceType\":\"MAPLECUTTER\"},{\"merchantId\":\"5ZTFCGXQKVZNA\",\"boarded\":false,\"provisioned\":true,\"serialNumber\":\"C050UQ75150054\",\"equipmentCode\":\"1297\",\"equipmentCodeDesc\":\"Clover Station 2018\",\"provisionedDeviceType\":\"GOLDENOAK\"}]}}";
CloverMerchant cv = mapper.readValue(str, CloverMerchant.class);
System.out.println(cv.getId()); //5ZTFCGXQKVZNA
System.out.println(cv.getEquipment().getElements().size()); //2

If you can check above the main method, I am able to deserialize it from Json String posted in the question.
I am using Jackson 2.9.8

dkb
  • 4,389
  • 4
  • 36
  • 54