I am trying to parse/convert a get response to a POJO. I have the User class below and the Controller class.
In the getUsers() method, I am able to parse the request by using ParameterizedTypeReference with wrapper class. However, I am not able to parse the "single object" response.
For getUser response, if I use the same code by changing the ParameterizedTypeReference<UsersWrapper>() as ParameterizedTypeReference<User>() or use the code shown in the getUser method, I get null values for my User class.
I assume I am not able to parse the JSON because of the { "user": {.. wrapper.
How can I have the values for the User class from JSON by using:
#GetMapping("/{id}")
public User getUser(#PathVariable long id) {}
JSON:
{
"user": {
"id": 375607441100,
"url": "https://example.com/users/375607441100.json",
"name": "example-user",
"email": "example-user#hotmail.com",
"created_at": "2020-11-25T09:13:40Z",
"updated_at": "2020-11-25T09:16:44Z",
"time_zone": "Europe/Warsaw",
"iana_time_zone": "Europe/Warsaw",
"phone": null,
"shared_phone_number": null,
"photo": null,
"locale_id": 1,
"locale": "en-US",
"organization_id": null,
"role": "admin",
"verified": true,
"external_id": null,
"tags": [],
"alias": null,
"active": true,
"shared": false,
"shared_agent": false,
"last_login_at": "2020-11-25T09:16:35Z",
"two_factor_auth_enabled": null,
"signature": null,
"details": null,
"notes": null,
"role_type": null,
"custom_role_id": null,
"moderator": true,
"ticket_restriction": null,
"only_private_comments": false,
"restricted_agent": false,
"suspended": false,
"chat_only": false,
"default_group_id": 360005501980,
"report_csv": false,
"user_fields": {}
}
}
User class:
#Data
public class User {
private long id;
private String name;
private String email;
private String role;
}
UsersWrapper:
#Data
#AllArgsConstructor
public class UsersWrapper {
private List<User> users = new ArrayList<>();
public UsersWrapper() {
}
}
Controller getUsers():
#GetMapping
public List<User> getUsers() {
UsersWrapper claims = new UsersWrapper();
try {
ResponseEntity<UsersWrapper> claimResponse = restTemplate.exchange(
resourceUrl,
HttpMethod.GET,
request(), // headers with basicAuth -> username:token
new ParameterizedTypeReference<UsersWrapper>() {
});
if (claimResponse != null && claimResponse.hasBody()) {
claims = claimResponse.getBody();
}
} catch (
RestClientException e) {
e.printStackTrace();
}
List<User> users = claims.getUsers();
return users;
}
getUser():
#GetMapping("/{id}")
public User getUser(#PathVariable long id) {
String url = resourceUrl + "/" + id;
ResponseEntity<User> response = restTemplate.exchange(
url,
HttpMethod.GET,
request(), User.class);
User user = response.getBody();
return user;
}
Creating the following wrapper class with #JsonProperty("user") solved the case.
#Data
#AllArgsConstructor
public class UserWrapper {
private UserDTO user;
public UserWrapper() {
}
#JsonProperty("user")
public UserDTO getUser() {
return user;
}
}
Related
I have problem while deserializing JSON to Java Object. I have models and views as shown below:
public class View {
public static class CreateIpSuccessResponse {}
public static class CreateIpErrorResponse {}
}
I use this views in this classes:
Root class:
#Data
#NoArgsConstructor
#AllArgsConstructor
public class CreateIpResponse {
#JsonProperty(value = "pResponseCode")
#JsonView({View.CreateIpSuccessResponse.class, View.CreateIpErrorResponse.class})
private Object pResponseCode;
#JsonProperty(value = "pResponse")
#JsonView({View.CreateIpSuccessResponse.class, View.CreateIpErrorResponse.class})
private CreateIpPResponse createIpPResponse;
}
First subclass:
#Data
public class CreateIpPResponse {
#JsonProperty("Status")
#JsonView({View.CreateIpSuccessResponse.class, View.CreateIpErrorResponse.class})
private String status;
#JsonProperty("Result")
#JsonView({View.CreateIpSuccessResponse.class, View.CreateIpErrorResponse.class})
private CreateIpResult result;
#JsonProperty("responseCode")
#JsonView({View.CreateIpSuccessResponse.class, View.CreateIpErrorResponse.class})
private String responseCode;
}
Second subclass:
#Data
public class CreateIpResult {
#JsonProperty(value = "partyid")
#JsonView(View.CreateIpSuccessResponse.class)
private String partyId;
#JsonProperty(value = "Error")
#JsonView(View.CreateIpErrorResponse.class)
private String error;
}
Example of my json deserialization:
public CreateIpResponse createIp(CreateIpRequest createIpRequest) throws IOException, SQLException {
String pRequest = new ObjectMapper().writer().withDefaultPrettyPrinter().writeValueAsString(createIpRequest);
Map<String, Object> response = openAccountRepository.callProcedure(pRequest, "createClientIP");
BigDecimal responseCode = (BigDecimal) response.get("pResponseCode");
if (responseCode.equals(new BigDecimal("200"))) {
return mapper
.readerWithView(View.CreateIpSuccessResponse.class)
.forType(CreateIpResponse.class)
.readValue(mapper.writeValueAsString(response));
} else {
return mapper
.readerWithView(View.CreateIpErrorResponse.class)
.forType(CreateIpResponse.class)
.readValue(mapper.writeValueAsString(response));
}
}
When I deserialize CreateIpSuccessResponse view, I expect:
{
"pResponseCode": 200,
"pResponse": {
"Status": "OK",
"Result": {
"partyid": "98493305"
},
"responseCode": "200"
}
}
But I get:
{
"pResponseCode": 200,
"pResponse": {
"Status": "OK",
"Result": {
"partyid": "98493305",
"Error": null
},
"responseCode": "200"
}
}
and vice versa, when I deserialize CreateIpErrorResponse view, I expect:
{
"pResponseCode": 400,
"pResponse": {
"Status": "Error",
"Result": {
"Error": "Некорректная дата выпуска"
},
"responseCode": "200"
}
}
But I get:
{
"pResponseCode": 400,
"pResponse": {
"Status": "Error",
"Result": {
"partyid": null,
"Error": "Некорректная дата выпуска"
},
"responseCode": "200"
}
}
My question is why i don`t getting result that i need?
It seems that ObjectMapper is not ignoring null values when serializing objects. So when creating he object mapper use the setSerializationInclusion(Include.NON_NULL) method call to tell the ObjectMapper to ignore the null values:
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(Include.NON_NULL);
You can find the details here
Edit: added the summarization of the solution as moken suggested in comments.
i have JSON :
{
"id": "string",
"name": "string",
"port": 0,
"location": "string",
"useCustomLocation": true,
"inMemoryMode": true,
"enabled": true,
"active": true,
"autoStartup": true,
"partitions": [
{
"id": "string",
"name": "string",
"factorUser": {
"username": "string",
"password": "string",
"admin": true,
"perms": "string"
},
"users": [
{
"username": "string",
"password": "string",
"admin": true,
"perms": "string"
}
]
}
]
}
My pojo classes:
public class Root {
private String id;
private String name;
private long port;
private String location;
private boolean useCustomLocation;
private boolean inMemoryMode;
private boolean enabled;
private boolean active;
private boolean autoStartup;
private Partition[] partitions;
//Getter and Setters simple variebles
public Partition[] getPartitions() {
return partitions;
}
public void setPartitions(Partition[] value) {
this.partitions = value;
}
}
Partition class:
public class Partition {
private String id;
private String name;
private User factorUser;
private User[] users;
//Getter and Setters simple variebles
public User getFactorUser() {
return factorUser;
}
public void setFactorUser(User value) {
this.factorUser = value;
}
public User[] getUsers() {
return users;
}
public void setUsers(User[] value) {
this.users = value;
}
}
and the next two classes work similarly(FactorUser and User)
my Test:
public void postBaseData() {
Root root = new Root();
Response response = given()
.contentType(ContentType.JSON)
.log().all()
.auth()
.preemptive()
.basic("login", "password")
.body(root)
.baseUri(BaseUrl + STORE_INSTANCE)
.when()
.post()
.then()
.extract().response();
System.out.println(response.getBody().asString());
Assert.assertEquals(200, response.statusCode());
}
Why is only part of the request sent to me? And therefore returning status code 400
Part of body which posted:
{
"id": null,
"name": null,
"port": 0,
"location": null,
"useCustomLocation": false,
"inMemoryMode": false,
"enabled": false,
"active": false,
"autoStartup": false,
"partitions": null
}
I understand that the error is somewhere in the initialization of nested classes, for example "partition", but I can not understand how to do it correctly.I asked a similar question with get, but for a long time I can’t figure out how to work with such complex json requests. I also tried the line: "private Partition[] partitions" changing to "private List<Partition> partitions" and etc... but I still can't send full json.
i don't use constructor because in POSTMAN i get 200 ok with empty fields
scr
I have this object class that has a list of customers as an attribute:
#Data
#NoArgsConstructor
#AllArgsConstructor
public class PeopleDTO {
private String processType;
private String operation;
private String entity;
private String entityType;
private Long id;
private Document document;
#Getter
#Setter
class Customer {
private String systemId;
private String customerId;
}
private List<Customer> customers;
}
This list is retrieved calling another microservice using webclient as follows:
public Mono<CuCoPerson> getCuCoPerson(Integer cucoId, String GS_AUTH_TOKEN) {
WebClient webClient = WebClient.create();
return webClient.get()
.uri(GET_RELATION_BY_ID + cucoId)
.header("Accept", "application/json")
.header("Authorization", GS_AUTH_TOKEN)
.retrieve()
.bodyToMono(CuCoPerson.class)
.map(cuCoPerson -> {
List<CustomerRelation> matches = cuCoPerson.getRelatedCustomers()
.stream()
.filter(relation -> relation.getSystemId().equals(400) || relation.getSystemId().equals(300) || relation.getSystemId().equals(410))
.filter(relation -> relation.getCustomerId().contains("F"))
.collect(Collectors.toList());
cuCoPerson.setRelatedCustomers(matches);
return cuCoPerson;
});
}
This method return a cucoPerson as follows:
{
"id": 1,
"relatedCustomers": [
{
"customerId": "xxx",
"systemId": 999
}
]
}
So now I want to add this object to my PeopleDTO class, but I don't know how. This is what I've done son far (hardcoded):
public PeopleDTO createPeople(Long id) {
PeopleDTO people = new PeopleDTO();
people.setProcessType("ONLINE");
people.setOperation("UPDATE");
people.setEntity("DOCUMENT");
people.setEntityType("DOCUMENT");
people.setIdCuco(id);
people.setDocument(new Document());
people.setCustomers(......);
}
So as you can see I don't know how to add a Mono in the last line.
The expected result should be like this:
{
"type": "ONLINE",
"operation": "UPDATE",
"id": 1,
"entity": "DOCUMENT",
"entityType": "NIE",
"documents": {
"id": 1,
"additionals": {
"issuing_authority": "Spain",
"country_doc": "ES",
"place_of_birth": "",
"valid_from": "1995-08-09",
"valid_to": "0001-01-01"
},
"code": "X12345",
"typeDocument": "NIE"
},
"id": 1,
"relatedCustomers": [
{
"customerId": "xxx",
"systemId": 999
}
]
}
first, create a list of customers like:
List<Customer> customers=new ArrayList<>;
Then add all the Customers to it one by one using a loop,
then you can directly add that to your object like
people.setCustomers(customers);
your object assignment should look something like:
public PeopleDTO createPeople(Long id) {
PeopleDTO people = new PeopleDTO();
people.setProcessType("ONLINE");
people.setOperation("UPDATE");
people.setEntity("DOCUMENT");
people.setEntityType("DOCUMENT");
people.setIdCuco(id);
people.setDocument(new Document());
List<Customer> customers=new ArrayList<>;
//add data to customer
people.setCustomers(customers);
}
The current response from my Spring REST service is as below :
[
{
"id": "5cc81d256aaed62f8e6462f4",
"email": "exmaplefdd#gmail.com"
},
{
"id": "5cc81d386aaed62f8e6462f5",
"email": "exmaplefdd#gmail.com"
}
]
I want to wrap that in a json object as below :
{
"elements":[
{
"id": "5cc81d256aaed62f8e6462f4",
"email": "exmaplefdd#gmail.com"
},
{
"id": "5cc81d386aaed62f8e6462f5",
"email": "exmaplefdd#gmail.com"
}
]
}
The controller :
#RequestMapping(value = "/users", method = GET,produces = "application/xml")
#ResponseBody
public ResponseEntity<List<User>> getPartnersByDate(#RequestParam("type") String type, #RequestParam("id") String id) throws ParseException {
List<User> usersList = userService.getUsersByType(type);
return new ResponseEntity<List<User>>(usersList, HttpStatus.OK);
}
User model class :
#Document(collection = "user")
public class User {
#Id
private String id;
private String email;
}
How can I implement this?
You could make a new Object to serialize:
class ResponseWrapper {
private List<User> elements;
ResponseWrapper(List<User> elements) {
this.elements = elements;
}
}
Then return an instance of ResponseWrapper in your controller method:
#RequestMapping(value = "/users", method = GET,produces = "application/xml")
#ResponseBody
public ResponseEntity<ResponseWrapper> getPartnersByDate(#RequestParam("type") String type, #RequestParam("id") String id) throws ParseException {
List<User> usersList = userService.getUsersByType(type);
ResponseWrapper wrapper = new ResponseWrapper(usersList);
return new ResponseEntity<ResponseWrapper>(wrapper, HttpStatus.OK);
}
The structure of JSON looks like:
{
"id": "0001",
"type": "portable",
"name": "mobile",
"results":[
{
"company": "Apple",
"country": "US",
"city": "Cupertino"
},
{
"company": "Google",
"country": "Japan",
"city": "Tokyo"
}
]
}
I tried to map the above json to my "Response" class but I could only retrieve id, type and name. For json object "results" is shows results:[].
Here is the code I have implemented;
CompanyDetail class:
#JsonIgnoreProperties(ignoreUnknown = true)
public class CompanyDetail {
public String company;
public String country;
public String city;
//getters and setters
}
Company class:
#JsonIgnoreProperties(ignoreUnknown = true)
public class CompanyD {
public String name;
public List<Detail> result;
//getters and setters
}
Implementation class:
#Override
public ResponseEntity<String> getResponseEntity() {
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate .getForEntity(
"url", String.class);
logger.info("Response:"+response);
return response;
}
#Override
public Company getResponseObject() {
RestTemplate restTemplate=new RestTemplate();
Company comp=(Company) restTemplate.getForObject("url",
Company.class,200);
List<CompanyDetail> companyInfo = comp.getCompanyDetail();
for (CompanyDetail companyDetail : companyInfo) {
logger.info("Country:"+companyDetail.getCountry());
logger.info("City:"+companyDetail.getCity());
logger.info("Company:"+companyDetail.getCompany());
}
return comp;
From both the implementation method I am getting null values for the "results" json object. I could not figure out what is wrong with my code.
Thanks in advance.
I'm having the same issue however in your case it looks like you misspelled "resluts".