I am not able to deserialize nested JSON array from response JSON using Spring Rest template.
JSON response which I am consuming is as follows
[
{
"creationTime": "2023-01-13",
"code": "456",
"cid": "123",
"priority": "CRITICAL",
"reviewDate": null,
"systemCall": [
{
"creationTime": "2023-01-13",
"status": null,
"id": "787878",
"modificationTime": "2023-01-13",
"creatorId": "ABC"
},
{
"creationTime": "2023-01-14",
"status": null,
"id": "787879",
"modificationTime": "2023-01-14",
"creatorId": "DEF"
}
],
level: "1"
}
]
And My model classes as follows
public class Resolution {
private String creationTime;
private String code;
private String cid;
private String priority;
private String reviewDate
private List<SystemCallVo> systemCall;
private String level;
public Resolution(){
}
//Getters and Settrs
}
public class SystemCallVo {
private String creationTime;
private String status;
private String id;
private String modificationTime;
private String creatorId;
public SystemCallVo(){
}
//Getters and Setters
}
public class ResolutionVo extends Resolution{
public ResolutionVo(){
}
}
I am calling my endpoint using rest template as follows.
ResponseEntity<List<ResolutionVo>> response = this.restTemplateConfig.restTemplate().exchange(builder.toUriString(), HttpMethod.POST, httpEntity, new ParameterizedTypeReference<List<ResolutionVo>>() {
}, new Object[0]);
Problem is List systemCall object is always null in response received through resttemplate even though systemCall attribute is present in JSON whenever I hit endpoint through swagger.
There is a defect in RestTemplate.exchange that prevents the deserialisation of even moderately complex JSON objects.
Read the response as a String and then deserialise to List<ResolutionVo> with an com.fasterxml.jackson.databind.ObjectMapper instance as follows:
ResponseEntity<String> response = this.restTemplateConfig.restTemplate().exchange(builder.toUriString(), HttpMethod.POST, httpEntity, String.class, new Object[0]);
String body = response.getBody();
List<ResolutionVo> value = objectMapper.readValue(body, new TypeReference<List<ResolutionVo>>() {});
I think this is a related issue.
Related
I am calling an endpoint that returns back a JSON response.
Here is sample of the JSON response:
{
"main": {
"test":{
"Date": "2022-06-06",
"Id": 1234
},
"response" :[
{
"responseTime": 100,
"redirects": 0
}
]
}
}
Here is my code to get the JSON response:
HttpEntity<String> request = new HttpEntity<>(setHeaders());
ResponseEntity<Main> response = restTemplate.exchange(endpoint, HttpMethod.GET, request, Main.class);
I want to convert the response to an entity object, with the response section being a HashMap. I tried the following but I get an error that the conversion failed
public class Main {
private Test test;
private Response response;
}
public class Test{
private Date Date;
private int Id;
}
public class Response{
private Map<String, String> responseMap;
}
Can someone help me understand what I am doing wrong?
what you are getting back is an Object containing a main object
{
"main": {
"test":{
"Date": "2022-06-06",
"Id": 1234
},
"response" :[
{
"responseTime": 100,
"redirects": 0
}
]
}
}
which means
// Can be named whatever
public class Response {
private Main main;
//constructor, getter setters
}
public class Main {
private Test test;
private ArrayList<Data> response;
//constructor, getter setters
}
public class Test {
private LocalDate date;
private int id;
//constructor, getter setters
}
public class Data {
private int responseTime;
private int redirects;
//constructor, getter setters
}
And then you call and plase the response data in the top level object
ResponseEntity<Main> response = restTemplate.exchange(endpoint, HttpMethod.GET, request, Response.class);
REST API Request:
{ "name": "abc", "sal": "10000", "location": "Hyd" }
EmployeeRequest.java
id, name, sal, location --> setters and getters
EmployeeResponse.java
id, name, sal, location --> setters and getters
POST : /api/employee --> this should not be change
POST API response :
expected:
{ "id" : "123" }
I dont want other fields except ID in a response
Actual:
`{
"id": "123",
"name": "null",
"sal": "null",
"location": "null"
}
But i want response only ID not other fields for POST response, But its coming all the fields in EmployeeResponse.java
GET API(/api/employees/id) Response
{
"id" : "123"
"name": "abc",
"sal": "10000",
"location": "Hyd"
}
But i want response ALL fields as a GET Response in EmployeeResponse.java
Is there any way to restrict certain properties wont be part of REST API response, even though all properties same Response class. ?
you can use the #JsonIgnore annotation
#JsonIgnoreProperties(value = { "intValue" })
public class MyDto {
private String stringValue;
private int intValue;
private boolean booleanValue;
public MyDto() {
super();
}
}
or #JsonIgnore on field level
public class MyDto {
private String stringValue;
#JsonIgnore
private int intValue;
private boolean booleanValue;
public MyDto() {
super();
}
}
How to create a POJO class Of below mentioned JSOn Structure by a REST Service. Using RestTemplate.exchange i need to parse this in my java.class file and get approved_by value and use in java code. Below is the response structure:
{
"approval_rules_overwritten": true,
"rules": [
{
"id": 1,
"name": "Test",
"rule_type": "RuleTest",
"approvals_required": 2,
"approved_by": [
{
"id": 2,
"name": "ABC",
"username": "ABC_XYZ",
"state": "active",
}
],
"approved": false
}
]
}
Did you create a class representing this JSON ?
In quick in the same class file (different classes would be best in different files)
public class Response {
private Boolean approval_rules_overwritten;
private List<Rule> rules;
public static class Rule {
private Integer id;
private String name;
private String rule_type;
private Integer approvals_required;
private List<Approval> approved_by;
private Boolean approved;
public static class Approval {
private String id;
private String name;
private String username;
private String state;
}
}
}
Also remember to add getters and setters on each class.
Now you can do your classic request:
ResponseEntity<Response> = restClient.exchange(request, Response.class);
and you would get your response.
You now only have to build your rest template and also to catch exceptions that could be thrown from the exchange request.
I did a get request to a external RESTful api and receive as response a json object with this structure:
{
"data": {
"id": 1,
"name": "John Doe",
"email": "doe#john.com",
"urlPicture": "urlPicture.com/82819",
"address": {
"street": "My street",
"number": "29",
"city": "Nurnberg",
"country": "Germany"
}
}
}
I don't need all stuff of this response, I want only some fields to save in a database.
My POJO classes are similar to this pseudocode:
public class Data{
private User user;
// getters and setters
}
public class User{
private int id;
private String name;
private String urlPicture;
private String country;
// getters and setters
}
But, when I try to extract fields that I want, I receive null in this fields
public void testResponse(){
RestTemplate restTemplate = new RestTemplate();
Data data = new Data();
User user = new User();
Gson gson = new Gson();
String response = restTemplate.getForObject(
"https://apifrommyrequest.com/user/{id}",
String.class,
73442);
user = gson.fromJson(response, User.class);
System.out.println(user);
}
```
My output:
22:20:57.641 [main] DEBUG org.springframework.web.client.RestTemplate - HTTP GET https://apifrommyrequest.com/user/73442
22:20:57.672 [main] DEBUG org.springframework.web.client.RestTemplate - Accept=[text/plain, application/json, application/*+json, */*]
22:20:58.243 [main] DEBUG org.springframework.web.client.RestTemplate - Response 200 OK
22:20:58.247 [main] DEBUG org.springframework.web.client.RestTemplate - Reading to [java.lang.String] as "application/json;charset=UTF-8"
Data(id=0, name=null, urlPicture=null, country=null)
I really don't know how to do anymore.
Try out the below code. You can't directly access the country, it is a value placed in a nested object. And also since response body returns as data you can't convert it to a User object. first, you need to convert it to a Data object.
public class User {
private int id;
private String name;
private String urlPicture;
private Address address;
// getters and setters
}
public class Address {
private String country;
// getters and setters
}
public void testResponse(){
RestTemplate restTemplate = new RestTemplate();
Data data = new Data();
User user = new User();
Gson gson = new Gson();
String response = restTemplate.getForObject(
"https://apifrommyrequest.com/user/{id}",
String.class,
73442);
data = gson.fromJson(response, Data.class);
System.out.println(data);
}
If you want, you can design your POJO like this too(to reduce nested POJOs):
public class Data {
private User data;
//getters and setters
}
public class User {
private int id;
private String name;
private String urlPicture;
private String country;
#JsonProperty("address")
private void unpackNested(Map<String,String> elements)
{
this.country = elements.get("country");
}
//getters and setters
}
Then finally deserialize on Data class
you dont really need to do the conversion from string to object, resttemplate already use jackson that do it for u , just have to
YourObject response = restTemplate.getForObject(
"https://apifrommyrequest.com/user/{id}",
YourObject.class,
73442);
then it is going to do the mapping to your pojo objects, u dont really need gson in this scenario.
Here is my Json response
"postedevent": [
{
"status": "true",
"event_id": "800",
"num_of_image_event": "0",
"title": "Testy",
"photo": "http://54.200.110.49/checkplanner/img/upload/21310059819profile_image_1409303464798.png",
"event_date": "2014-08-29",
"fullDate": "Friday - August 29, 2014",
"event_from": "12:00AM",
"event_to": "12:15AM",
"city": "Ahm",
"state": "CA",
"member_id": "471",
"username": "Krishna Mohan",
"pencil": "yes",
"attend": "yes",
"company": "Development"
}
]
this is java class to get java objs from json response
public class PostedEvent {
String status;
int event_id;
int num_of_image_event;
String title;
String photo;
String event_date;
String fullDate;
String event_from;
String event_to;
String city;
String state;
String member_id;
String username;
String pencil;
String attend;
String company;
}
public class PostedEvnetsList
{
ArrayList<PostedEvent> postedevent;
}
And I am parsing in this way
InputStream is = WebResponse.getResponse(url);
ObjectMapper mapper = new ObjectMapper();
PostedEvnetsList mList = null;
mList = mapper.readValue(is,PostedEvnetsList.class);
eventList = mList.postedevent;
I am getting following parse exception
jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "status" (Class com.example.jsonproforexam.PostedEvent), not marked as ignorable
I have declared same fields as in json response then why I am geting this exception
Please help
Your fields of PostedEvent and the PostedEvent field of PostedEventsList are not accessible.
You must set them as public (not recommended) or provide public getters and setters for them POJO-style.
Then Jackson will be able to de-serialize and the error will go away.
You can use the JsonProperty annotation to specify the json key
Ex:
public class PostedEvent {
#JsonProperty("status")
String status;
#JsonProperty("event_id")
String eventId;
....
....
If you have missed some fields from json in your entity class, you can use #JsonIgnoreProperties annotation to ignore the unknown fields.
#JsonIgnoreProperties(ignoreUnknown = true)
public class PostedEvent {
...