How to get JSON Object, REST API, Jhipster, SpringBoot - json

I'm coding an API using Jhipster. Server side is programmed with Spring-Boot. I want to get JSON Object that i send with PostMan
{
"user" : {
"name" : "name",
"surname": "surname"
}
}
I create a ressource and a class to get this JSON Object
#RequestMapping(value = "/",method = RequestMethod.POST,produces = MediaType.APPLICATION_JSON_VALUE)
#Timed
public ResponseEntity<AlertBalance> create(#RequestBody User user) throws URISyntaxException {
System.out.println("name "+ user.getName()+"/ surname : "+User.getSurname());
}
User class Code
#JsonIgnoreProperties(ignoreUnknown = true)
public class User implements Serializable {
private String name;
private String surname ;
#JsonCreator
public User(#JsonProperty("surname") String surname , #JsonProperty("name") String name){
this.surname = surname;
this.name = name;
}
public User(){
}
//setters and getters
}
The create() method is called when I do request from postman, but the value of name and surname is null. Do you know what I can do to get the real values ?

I just find the mistake, the JSON Object I sent was incompatible. I change it with
{
"name" : "name",
"surname": "surname"
}
and now it works.

Related

How to deserialize a json that contains a json array into an object that would contain a list?

{
"id" : "25",
"authors" :
[
{
"firstname":"Ayn",
"lastname":"Rand"
},
{
"firstname":"Mark",
"lastname" : "Twain"
}
]
}
Here is my Java class:
public class FavoriteAuthors {
public String id;
public List<Author> authors;
public static class Author {
public String firstname;
public String lastname;
}
}
I have already tried using the following 2 approaches:
FavoriteAuthors favAuthors = Json.fromJson(json, FavoriteAuthors.class);
and
ObjectMapper objectMapper = new ObjectMapper();
FavoriteAuthors favAuthors = objectMapper.readValue(json, FavoriteAuthors.class);
In both the approaches, I receive the following exception:
(no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
Could anyone please point me to the right approach here?

I sent correct JSON format body from Postman to my Path but I get 400 Bad Request error

I sent correct JSON Format body from Postman.
{
"loginId": "xxxxxx",
"password": "xxxxxx",
"clientIP": "xxxxx",
"companyId": "xxxxx"
}
This is my controller
#RestController
#RequestMapping(path = "/umm")
public class LoginServer {
private transient Logger log = LogManager.getLogger(this.getClass());
#RequestMapping(value = "/basicLogin",method = RequestMethod.POST)
public #ResponseBody LoginRequest login(#RequestBody(required = true) LoginRequest loginRequest){
return null;
}
}
And this is my domain
public class LoginRequest implements Serializable {
private static final long serialVersionUID = -884241731093688658L;
private String loginId;
private String password;
private String clientIP;
private String companyId;
public LoginRequest(String loginId, String password, String clientIP, String companyId) {
this.loginId = loginId;
this.password = password;
this.clientIP = clientIP;
this.companyId = companyId;
}
//getter and setter omitted
}
I don't know why it's return me 400 error code (Bad Request) because I sent a correct JSON body
This is Response message.
{
"timestamp": 1549458416991,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.http.converter.HttpMessageNotReadableException",
"message": "JSON parse error: Can not construct instance of escf.api.domain.login.LoginRequest: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of escf.api.domain.login.LoginRequest: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)\n at [Source: java.io.PushbackInputStream#1c360a55; line: 2, column: 2]",
"path": "/umm/basicLogin"
}
I need it's return me code 200.
add super(); in domain class it's work.
Given that you are using Jackson for serialization/deserialization instead of Gson, the following solution should work for you.
public class LoginRequest implements Serializable {
private static final long serialVersionUID = -884241731093688658L;
private String loginId;
private String password;
private String clientIP;
private String companyId;
#JsonCreator
public LoginRequest(#JsonProperty("loginId") String loginId, #JsonProperty("password") String password, #JsonProperty("clientIP") String clientIP, #JsonProperty("companyId") String companyId) {
this.setLoginId(loginId);
this.setPassword(password);
this.setClientIP(clientIP);
this.setCompanyId(companyId);
}
// Define your getters and setters IMPORTANT
}
Resources: https://www.baeldung.com/jackson-annotations

How to combine #JsonView with #JsonProperty?

I have a DTO class that should serve json via a spring-mvc #RestController.
I want to provide different version/views on the same object. Especially, there are fields that are only used in VERSION_1 of the api, and some only in VERSION_2.
Problem: I could add #JsonView for this, but my goal is also to rename those fields. Some fields should actually replace the same name from previous versions.
Example:
public class Person {
#JsonView(View.Version_1.class)
#JsonProperty("name")
private String name; //eg only the firstname
#JsonView(View.Version_2.class)
#JsonProperty("name")
private NameDTO namedto; //now changing to first+last name
static class NameDTO {
private String firstname;
private String lastname;
}
}
#RestController
public class MyServlet {
#GetMapping("/person/{id}")
#JsonView(View.Version_1.class)
public PersonDTO person1(int id) {
//...
}
#GetMapping("/person_new/{id}")
#JsonView(View.Version_2.class)
public PersonDTO person2(int id) {
//...
}
}
So, depending on the view/version, you would get the same json field firstname, but with different content.
In this example, using V1 would give:
{"name": "john"}
Whereas using V2 should result in:
{"name": {"firstname": "john", "lastname": "doe"}}
BUT not with he code above, as jackson complains:
com.fasterxml.jackson.databind.JsonMappingException: Conflicting
getter definitions for property "name".
Is that possible at all?
I found a way using:
https://github.com/jonpeterson/spring-webmvc-model-versioning
Basic idea is to add a custom VersionedModelConverter that is applied on #VersionedModelConverter annotated webservice response classes.
#Configuration
#Import(VersionedModelResponseBodyAdvice.class)
public class SpringMvcVersioningConfiguration {
//register in jackson. spring-boot automatically registers any module beans
#Bean
public Model versioningModel() {
return new VersioningModule();
}
}
#GetMapping
#VersionedResponseBody(defaultVersion = "2.0")
public Person person() {
}
#JsonVersionedModel(currentVersion = "3.0" toPastConverterClass = PersonConverter.class)
public class Person {
}
public class PersonConverter implements VersionedModelConverter {
#Override
public ObjectNode convert(ObjectNode modelData, String modelVersion, String targetModelVersion, JsonNodeFactory nodeFactory) {
Double modelv = Double.valueOf(modelVersion);
Double targetv = Double.valueOf(targetVersion);
//todo if-else based on model version
Object node = modelData.remove("fieldname");
//node.change...
modelData.set("fieldname_renamed", node);
}
}

JsonView does not work

I use the annotation #JsonView, but it doesn't work, here is my code and the return data, would you please help me to look where I am wrong.
My spring jar shows the edition of "spring-web-3.2.8.RELEASE.jar", and I just add this bean,I do not know whether it is useful or not, and I just use #JsonView directly in my code
<bean id = "jacksonMessageConverter" class = "org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
</bean>
Here is the View class
public class View {
public interface Summary{};
}
This is the User entity class(with "set" "get" method omitted), it has several attribute which corresponding to the database, there is a "status" attribute needn't return in the json data.
public Class User{
#JsonView(View.Summary.class)
private Integer uid;
#JsonView(View.Summary.class)
private String first;
#JsonView(View.Summary.class)
private String last;
#JsonView(View.Summary.class)
private String email;
#JsonView(View.Summary.class)
private String password;
private Integer status;
}
I had the controller
#RequestMapping(value="/login", method=RequestMethod.POST)
#JsonView(View.Summary.class)
#ResponseBody
public Message login(String email, String password){
User user = userMapper.findUser(email,password);
Message message = new Message();
message.setUser(user);
return message;
}
}
and here is my Message class with the "set" "get" methods
public class Message {
private int box_hits;
private List<Box> boxes;
#JsonView(View.Summary.class)
private User user;
}
when I use the postman to test the url,it shows json data, obviously, it should not return with the attribute without #JsonView, what' wrong with my code?
{
"box_hits": 0,
"boxes": null,
"user": {
"uid": 1,
"first": "yuan",
"last": "kang",
"email": "123#qq.com",
"password": "123",
"status": 0
}
}
As described in the announcement blog post, this feature is only available as of Spring Framework 4.2. It won't work with Spring 3.2.8.

Parse a json object with multiple sub-objects inside with GSON

i have an issue with the response of an API that i want to use, i was developing an APP that consumes this API using Retrofit 1.9.0 and GSON 2.3.1.
The Json that i want to parse is like:
{
"user1": {
"id": 1,
"name": "foo",
"address": "bar"
},
"user2":{
"id": 2,
"name": "foo",
"addres":"bar"
},
... it can be any number of users ...
"userN":{
"id": N,
"name": "foo,
"address": "bar"
}
}
So i have an POJO named User:
public class User{
private int id;
private String name;
private String address;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
I was trying to parse that json with the configuration Map<String, User>:
Callback< <Map<String, User> > callback
But when i run it, i have a GSON error:
gson expecting array but found object
How can i parse the json in a correct way?
PD: i can't change the API response, it's an external API.
Try specifying a concrete type for you callback, like HashMap. Map is an interface.
Callback< <HashMap<String, User> > callback;
Usually you will get casting exception instead of a parsing error, but worth a try.