Spring get response as json to object casting - java

When i go (hit URL in the browser) to some URL
I got a json response matching my Class fields (GET RESPONSE).
I want to converter this json to my object without using some Java converters like jackson.
What spring annotation could i use here?
What i try to do is something like that, so it automatically translates json to object:
#RequestMapping("/getCar")
public Car getCar(#SOMEANNOTATION(Car car)
{ return car;}

you can do it using RestTemplate:
RestTemplate restTemplate = new RestTemplate();
Car car = restTemplate.getForObject("http://localhost:8080/getCar", Car.class);
you need a Class car, so Spring can map it:
#JsonIgnoreProperties(ignoreUnknown = true)
public class Car {
...
}
but you need to understand, that Spring will still use some converter under the hood to create/read the data...

you can try this #Consumes({ "application/json", "application/xml" })

There's another solution from Sring Boot documentation Building a RESTful Web Service.
Basically, the serialization/deserialization of the object is handled automatically by Spring converter. In other word, you have nothing to do in this case.
Consider a basic REST controller :
package hello;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
#RequestMapping("/greeting")
public Greeting greeting(#RequestParam(value="name", defaultValue="World") String name) {
return new Greeting(counter.incrementAndGet(),
String.format(template, name));
}
}
Explanation
The Greeting object must be converted to JSON. Thanks to Spring’s HTTP
message converter support, you don’t need to do this conversion
manually. Because Jackson 2 is on the classpath, Spring’s
MappingJackson2HttpMessageConverter is automatically chosen to convert
the Greeting instance to JSON.

You have to use something like this to automatically convert your request body json to a Java Object.
#RequestMapping("/getCar", method =RequestMethod.POST,
produces=MediaType.APPLICATION_JSON_VALUE,consumes=MediaType.APPLICATION_JSON_VALUE)
public Car getCar(#RequestBody Car car){
return car;
}
However, Spring will use an HttpMessageConverter at the backend to convert your json request to a POJO. Something like this should be added to your #Configuration class
public void configureMessageConverters() {
List<HttpMessageConverter<?> messageConverters = new ArrayList<>();
messageConverters.add(new MappingJackson2HttpMessageConverter());
super.configureMessageConverters(converters);
}

Related

How send a Map<String, String> using #PathVariable from Spring MVC

I want to receive a Map<Timestamp, Integer> as PathVariable using Spring MVC. Is this possible?
This is my controller:
#ApiOperation(value = "Some Api", produces = MediaType.APPLICATION_JSON_VALUE)
#PostMapping(consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
public ResponseEntity<RestResult> createApi(#RequestPart (value="image", required = false) MultipartFile banner, SomeRequest request){
RestResult result = new RestResult();
return new ResponseEntity<>(result, HttpStatus.CREATED);
}
This is my request:
#Getter
#Setter
public class SomeRequest implements Serializable {
#NonNull
private MultiValueMap<Timestamp, Integer> someValue;
}
As one of the way you could use Spring's HandlerMethodArgumentResolver and implement its supportsParameter() and resolveArgument() methods. The last one accepts the method parameter and web request, which you can use to get any required data and compose the object whatever you want.
The argument resolver is invoked before the controller method and makes the required argument transformation.
Update:
You have to register the resolver to make it active. If you use spring-boot, you just need to define it as a bean.
Hope it will help.

How to convert spring-boot request parameter

Currently a request method receives a encoded token as parameter (this token is a String but not JSON or anything like that).
This token then gets decoded to a data class.
#GetMapping(value = "/api/xyz")
public ResponseEntity<XYZ> xyz(#NotBlank String token) {
Data data = Token.parse(token);
...
}
Is it possible to write a annotation similar to how #RequestBody works that converts a parameter into something else?
The request should just look like that instead:
#GetMapping(value = "/api/xyz")
public ResponseEntity<XYZ> xyz(#TokenParser Data data) {
...
}
This class / annotation should contain the code necessary to convert the token (String) to my data class.
The request method should just have the converted data class as parameter.
I solved it with the spring-boot Converter.
import javax.inject.Inject;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
#Component
public class TokenConverter implements Converter<String, Data> {
private final TokenParser tokenParser;
#Inject
public TokenConverter(TokenParser TokenParser) {
this.tokenParser = tokenParser;
}
#Override
public Data convert(String token) {
return tokenParser.parse(token);
}
}
Just add such a converter anywhere in your project.
The mapping is managed by spring-boot.
New request:
#GetMapping(value = "/api/method")
public ResponseEntity<Data> method(#RequestParam("token") Data data) {
...
}
For more information: https://www.baeldung.com/spring-mvc-custom-data-binder
I hope it helps someone else.

Best practice to deserialize a JSON using Spring MVC

I'm developing a web application using Spring MVC; it works as follows:
a JSON request is created from a model object (a POJO)
it's sent to an external server that exposes some APIs
a JSON response is received by the controller
I need to figure out which is the best way to serialize and deserialize JSON in a Java web application. At first I was using Gson but then I began to wonder if it was the right choice.
Is it possible to serialize and deserialize JSON to/from model
object using #RestController annotation? How does it works? I only find examples of how to create a rest service, in this sense
What is the best practice in this case? RestController? Gson? Jackson? Other?
N.B. My JsonResponse object has a generic field because the responses are all the same except that for a value. An example:
AccountRequest.class
public class AccountRequest() {
private String jsonrpc;
private String method;
private Map<String, Object> params;
private int id;
//constructor, getters and setters
}
JsonResponse.class
public class JsonResponse<T> {
private String jsonrpc;
private T result;
private String id;
//constructor, getters and setters
}
LoginResult.class
public class LoginResult {
private String token;
private String product;
private String error;
private Date lastLoginDate;
//constructor, getters and setters
}
MyController.class
#Controller
public class LoginController {
String response;
[...]
#RequestMapping(value = "/login", method = RequestMethod.POST)
public ModelAndView doLogin(#ModelAttribute("user") User user) {
[...]
//???
[...]
}
}
I open connection, send request and save the response in response String in MyController class. User parameter is annotated with #ModelAttribute to retrive the User object created by the showLoginForm() method.
Using Gson I know how to serialize request from my model object:
AccountRequest accountRequest = new AccountRequest();
accountRequest.setJsonrpc("2.0");
accountRequest.setMethod("method");
accountRequest.setParams(params);
accountRequest.setId(1);
String gson = new Gson().toJson(accountRequest);
JSONObject accountRequestJson = new JSONObject(gson);
And how to deserialize response in my model object:
Type jsonType = new TypeToken<JsonResponse<LoginResult>>() {}.getType();
JsonResponse<LoginResult> jsonResponse = new Gson().fromJson(response, jsonType);
The response is now saved into jsonResponse object, and I can put it in my ModelAndView.
Now, how can I deserialize it in my model object using #RestController and Jackson? Can you confirm it's the better method to do that? Can you post an example?
I hope it's not a silly question.
Thanks in advance!

Spring restful webservice returning JSON

I just took the tutorial over at Spring.io http://spring.io/guides/gs/rest-service/ and created a simple rest service. But, does anybody know how I can return multiple objects in JSON format? If I for instance have a person class with a name and an id, how can I add three persons to /persons?
You can use the #ResponseBody annotation and just return whatever you want, providing that those objects can be jsonized.
For example, you can have a bean like this:
#Data
public class SomePojo {
private String someProp;
private List<String> someListOfProps;
}
and then in your controller you can have:
#ResponseBody
#RequestMapping("/someRequestMapping")
public List<SomePojo> getSomePojos(){
return Arrays.<String>asList(new SomePojo("someProp", Arrays.<String>asList("prop1", "prop2"));
}
and Spring by default would use its Jackson mapper to do it, so you'd get a response like:
[{"someProp":"someProp", "someListOfProps": ["prop1", "prop2"]}]
The same way, you can bind to some objects, but this time, using the #RequestBody annotation, where jackson would be used this time to pre-convert the json for you.
what you can do is
#RequestMapping("/someOtherRequestMapping")
public void doStuff(#RequestBody List<SomePojo> somePojos) {
//do stuff with the pojos
}
Try returning a list from the method:
#RequestMapping("/greetings")
public #ResponseBody List<Greeting> greetings(
#RequestParam(value="name", required=false, defaultValue="World") String name) {
return Arrays.asList(new Greeting(counter.incrementAndGet(),String.format(template, name)));
}

How to force spring's #ResponseBody to use xmlConvertor

When I return a single object from a controller like this,
#ResponseBody
public MyClass module(...) {
...
}
I get the xml output on the client and log shows like this,
2011-09-07 18:22:06,963 [qtp1409490836-27] DEBUG
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
- Written [com.domain.MyClass#4374820d] as "application/xhtml+xml"
using
[org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter#b4e1f3]
But If I use a list like this,
#ResponseBody
public List<MyClass> module(...) {
...
}
It uses jsonConvertor and returns the json output.
2011-09-07 18:38:31,026 [qtp420370595-26] DEBUG
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
- Written [[com.domain.MyClass#654309f0]] as
"application/json;charset=UTF-8" using
[org.springframework.http.converter.json.MappingJacksonHttpMessageConverter#14419f80]
The MyClass is annotated with jaxb. In jersey I could say
#Produces({ MediaType.APPLICATION_XML })
How do I force spring to use the xmlconverter always?
There is some bug that means you cannot return your class in a list. You need to create a new class to hold your list of objects and return that in the #ResponseBody. Something like this:
#RequestMapping(value = Constants.URL, method = RequestMethod.GET)
public #ResponseBody ListHolder getFoos(HttpServletResponse response) {
response.setContentType("application/xml");
List<Foo> foos = getFoos();
ListHolder listHolder = new ListHolder();
listHolder.setFoos(foos);
return listHolder;
}
Annotate your ListHolder class with #XmlRootElement and if your have the jaxb jar or Java 6 then it should work.
If Spring cant find a JSON convert it can't send JSON. Try to remove jackson.jar from the class path and it should default to XML through XStream for all request.

Categories