Search code examples
javaspring-bootrestresttemplateresponse-entity

RestTemplate Post and response ( JSON ) Spring boot


I am implementing a post with restTemplate, with body an object representing a fields of a json and I would like the answer with an object representing the json fields of the answer itself.

For example, the json is this:

{
    "content": {
        "name": "support-callmebackmodals-view_web",
        "data": {
            "channel": "web",
            "productName": "book"
        }
    }
}

The class that represents it is this:

@Getter
@Setter
@NoArgsConstructor
public class Request {
    Con ContentObject;
}

ConClass contains "content" of json, content contains name and DataClass ecc.

The response translated into object I created is:

@Getter
@Setter
@NoArgsConstructor
@ToString
public class AssistenzaResponse {
    
    private boolean success;
    private String error;
    Results results;
}

@Getter
@Setter
@NoArgsConstructor
public class Results {

    Content content;
}

@Getter
@Setter
@NoArgsConstructor
public class Content {
    Meta meta;
    private String name;
    private String html;
    private float duration;
    private float statusCode;
    private boolean success;
    private String error;
}

@Getter
@Setter
@NoArgsConstructor
public class Meta {
    private String src;
}

My service is this:

@Service
public class AssistenzaService {
    public AssistenzaResponse getUno() throws IOException {

        String url = "https://support.aasdt/batch";


        org.apache.http.client.HttpClient client = HttpClientBuilder.create().build();

        Request request1 = new Request();
        Con con = new Con();
        con.setName("support-callmebackmodals-view_web");

        Data data = new Data();
        data.setChannel("web");
        data.setProductName("LibrettoMinori");
        con.setData(data);
        RestTemplate restTemplate = new RestTemplate();
        request1.setContentObject(con);
        HttpHeaders headers = new HttpHeaders();
        headers.set("Content-Type", "application/json");
        headers.set("Accept", "application/json");
        HttpEntity<Request> entity = new HttpEntity<>(request1, headers);

        try {
            ResponseEntity<AssistenzaResponse> response = restTemplate.exchange(url, HttpMethod.POST, entity, AssistenzaResponse.class);

            return response.getBody();

        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return null;
    }
}

But the answer is not what I expect, because it returns:

{
    "success": true,
    "error": null,
    "results": {
        "results": null
    }
}

Instead if I use:

ResponseEntity<String> response = restTemplate.exchange(url,HttpMethod.POST, entity, String.class);         

The response is correct and it is:

{
    "success": true,
    "error": null,
    "results": {
        "content": {
            "name": "support-callmebackmodals-view_web",
            "html": "",
            "meta": {
                "src": "/support/client.js"
            },
            "duration": 7.694401,
            "statusCode": 200,
            "success": true,
            "error": null
        }
    }
}

Why don't I get the exact answer using the answer object I created?

But if I use the string it works?

I expect that the json answer will not be returned as String, but as my Response object, I tried to use also postForObject and postForEntity.


Solution

  • The problem is that the structure of the JSON response you are receiving does not match the structure of the AssistenzaResponse class you are using for deserialization. Therefore, RestTemplate cannot correctly convert the JSON response into an AssistenzaResponse object.

    You can fix this by changing the AssistenzaResponse class to match the structure of the JSON response you are receiving. In your case, you need to add one more level of nesting to the AssistenzaResponse class. This can be done, for example, as follows:

    @Getter
    @Setter
    @NoArgsConstructor
    public class AssistenzaResponse {
        private boolean success;
        private String error;
        private Results results;
    
        @Getter
        @Setter
        @NoArgsConstructor
        public static class Results {
            private Content content;
    
            @Getter
            @Setter
            @NoArgsConstructor
            public static class Content {
                private String name;
                private String html;
                private Meta meta;
                private float duration;
                private float statusCode;
                private boolean success;
                private String error;
    
                @Getter
                @Setter
                @NoArgsConstructor
                public static class Meta {
                    private String src;
                }
            }
        }
    }
    

    You can then use AssistenzaResponse instead of String when calling RestTemplate.exchange() like you did before:

    ResponseEntity<AssistenzaResponse> response = restTemplate.exchange(url, HttpMethod.POST, entity, AssistenzaResponse.class);
    return response.getBody();
    

    The RestTemplate should now properly convert the JSON response into an AssistenzaResponse object. Try it!