To return JSON from the server, you must include the JSON data in the body of the HTTP response message and provide a "Content-Type: application/json" response header. The Content-Type response header allows the client to interpret the data in the response body correctly.
These JSONObject values can be accessed by using the various corresponding accessor methods. The get() method returns a value if it founds and throws an exception if the value not found. While the opt() method returns the default value instead of throwing the exception. The value may be null.
As you are using Spring Boot web, Jackson dependency is implicit and we do not have to define explicitly. You can check for Jackson dependency in your pom.xml
in the dependency hierarchy tab if using eclipse.
And as you have annotated with @RestController
there is no need to do explicit json conversion. Just return a POJO and jackson serializer will take care of converting to json. It is equivalent to using @ResponseBody
when used with @Controller. Rather than placing @ResponseBody
on every controller method we place @RestController
instead of vanilla @Controller
and @ResponseBody
by default is applied on all resources in that controller.
Refer this link: https://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-responsebody
The problem you are facing is because the returned object(JSONObject) does not have getter for certain properties. And your intention is not to serialize this JSONObject but instead to serialize a POJO. So just return the POJO.
Refer this link: https://stackoverflow.com/a/35822500/5039001
If you want to return a json serialized string then just return the string. Spring will use StringHttpMessageConverter instead of JSON converter in this case.
The reason why your current approach doesn't work is because Jackson is used by default to serialize and to deserialize objects. However, it doesn't know how to serialize the JSONObject
. If you want to create a dynamic JSON structure, you can use a Map
, for example:
@GetMapping
public Map<String, String> sayHello() {
HashMap<String, String> map = new HashMap<>();
map.put("key", "value");
map.put("foo", "bar");
map.put("aa", "bb");
return map;
}
This will lead to the following JSON response:
{ "key": "value", "foo": "bar", "aa": "bb" }
This is a bit limited, since it may become a bit more difficult to add child objects. Jackson has its own mechanism though, using ObjectNode
and ArrayNode
. To use it, you have to autowire ObjectMapper
in your service/controller. Then you can use:
@GetMapping
public ObjectNode sayHello() {
ObjectNode objectNode = mapper.createObjectNode();
objectNode.put("key", "value");
objectNode.put("foo", "bar");
objectNode.put("number", 42);
return objectNode;
}
This approach allows you to add child objects, arrays, and use all various types.
You can either return a response as String
as suggested by @vagaasen or you can use ResponseEntity
Object provided by Spring as below. By this way you can also return Http status code
which is more helpful in webservice call.
@RestController
@RequestMapping("/api")
public class MyRestController
{
@GetMapping(path = "/hello", produces=MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Object> sayHello()
{
//Get data from service layer into entityList.
List<JSONObject> entities = new ArrayList<JSONObject>();
for (Entity n : entityList) {
JSONObject entity = new JSONObject();
entity.put("aa", "bb");
entities.add(entity);
}
return new ResponseEntity<Object>(entities, HttpStatus.OK);
}
}
you can also use a hashmap for this
@GetMapping
public HashMap<String, Object> get() {
HashMap<String, Object> map = new HashMap<>();
map.put("key1", "value1");
map.put("results", somePOJO);
return map;
}
More correct create DTO for API queries, for example entityDTO:
@GetMapping(produces=MediaType.APPLICATION_JSON_VALUE) @ResponseStatus(HttpStatus.OK) public List<EntityDto> getAll() { return entityService.getAllEntities(); }
But if you need return different Map parameters you can use next two examples
2. For return one parameter like map:
@GetMapping(produces=MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<Object> getOneParameterMap() { return ResponseEntity.status(HttpStatus.CREATED).body( Collections.singletonMap("key", "value")); }
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<Object> getSomeParameters() { return ResponseEntity.status(HttpStatus.OK).body(Map.of( "key-1", "value-1", "key-2", "value-2", "key-3", "value-3")); }
@RequestMapping("/api/status")
public Map doSomething()
{
return Collections.singletonMap("status", myService.doSomething());
}
PS. Works only for 1 value
use ResponseEntity<ResponseBean>
Here you can use ResponseBean or Any java bean as you like to return your api response and it is the best practice. I have used Enum for response. it will return status code and status message of API.
@GetMapping(path = "/login")
public ResponseEntity<ServiceStatus> restApiExample(HttpServletRequest request,
HttpServletResponse response) {
String username = request.getParameter("username");
String password = request.getParameter("password");
loginService.login(username, password, request);
return new ResponseEntity<ServiceStatus>(ServiceStatus.LOGIN_SUCCESS,
HttpStatus.ACCEPTED);
}
for response ServiceStatus or(ResponseBody)
public enum ServiceStatus {
LOGIN_SUCCESS(0, "Login success"),
private final int id;
private final String message;
//Enum constructor
ServiceStatus(int id, String message) {
this.id = id;
this.message = message;
}
public int getId() {
return id;
}
public String getMessage() {
return message;
}
}
Spring REST API should have below key in response
you will get final response below
{
"StatusCode" : "0",
"Message":"Login success"
}
you can use ResponseBody(java POJO, ENUM,etc..) as per your requirement.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With