Skip to content

How to return custom response in Spring with several attributes other than the List

I’m trying to get a custom response back from a spring rest controller back to the user, containing a list of all registered users and other keys such as sucess, etc. I tried the following approach but the Json array is completly escaped as a string…

@GetMapping(value = "/workers", produces = "application/json;charset=UTF-8")
public ResponseEntity<String> getAllWorkers() throws JSONException {
    JSONObject resp = new JSONObject();
    ObjectMapper objectMapper = new ObjectMapper();

    HttpStatus status;
    try {
        ObjectMapper mapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
        List<Worker> workers = workerservice.getAllworkers();
        String json = mapper.writeValueAsString(workers);
        
        resp.put("success", true);
        resp.put("info", json);
        status = HttpStatus.OK;
    } catch (Error | JsonProcessingException e) {
        resp.put("success", false);
        resp.put("info", e.getMessage());
        status = HttpStatus.INTERNAL_SERVER_ERROR;
    }

    return new ResponseEntity<>(resp.toString(),status);
}

I get something like this

{
    "success": true,
    "info": "[ {n  "id" : 3,n  "password" : "abcdefg", n  "tasks" : [ ], (...) ]"
}

and wanted something like:

{
    "success": true,
    "info": [ 
        {
           "id" : 3,
           "password" : "abcdefg",
           "tasks" : [ ]
        },
        (...) 
    ]"
}

Is there any way I can get the json array properly showed after a request?

Answer

You can let Spring Boot handle the serialization of the response entity.

Create a POJO which defines your response object.

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class WorkerPojo {
    @JsonProperty("success")
    private boolean success;
    @JsonProperty("info")
    private List<Worker> workerList;
    @JsonProperty("message")
    private String message;

    // A default constructor is required for serialization/deserialization to work
    public WorkerPojo() {
    }
    
    // Getters and Setters ....
}

This lets you simplify your getAllWorkers method a bit:

@GetMapping(value = "/workers", produces = "application/json;charset=UTF-8")
public ResponseEntity<WorkerPojo> getAllWorkers() throws JSONException {
    WorkerPojo response;
    try {
        List<Worker> workers = workerservice.getAllworkers();
        return new ResponseEntity<>(new WorkerPojo(true, workers, "OK"), HttpStatus.OK);
    } catch (Error e) {
        return new ResponseEntity<>(new WorkerPojo(false, null, e.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

Note that I added a separate message field for the error message. I find that clients are much happier if a specific field is not used for different types of data. “info” should never be anything else than a list of workers and “message” should never be anything else than a String.

Disclaimer: I didn’t have a Spring Boot project setup to test this properly. If something is not working let me know and I will check it.