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.
Related
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.
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();
}
}
I got a JSON response like this:
{
"status": "success",
"response": {
"entries": [
{
"id": 1,
"value": "test"
},
{
"id": 2,
"value": "test2"
}
]
}
}
And i want to map it with jackson-databind on an object like this:
public class Response {
#JsonProperty("status")
private String status;
#JsonProperty("response.entries")
private Collection<ResponseEntry> entries;
}
So i'm searching for an way to give #JsonProperty a path so it can skip the layer "response".
Welcome to Stack Overflow. You can define a wrapper class for your Collection<ResponseEntry> collection like below :
public class ResponseWrapper {
#JsonProperty("entries")
private Collection<ResponseEntry> entries;
}
The ResponseEntry class could be defined like below :
public class ResponseEntry {
#JsonProperty("id")
private int id;
#JsonProperty("value")
private String value;
}
Once defined these classes you can rewrite your old Response class like below :
public class Response {
#JsonProperty("status")
private String status;
#JsonProperty("response")
private ResponseWrapper responseWrapper;
}
You can flatten using the #JsonUnwrapped annotation.
You can have your classes like this
public class Response {
private String status;
private Collection<ResponseEntry> entries;
}
public class ResponseEntry {
#JsonUnwrapped
private Entry entry;
}
pubic class Entry{
private Integer id;
private String value;
}
Could someone point me in the right direction as to how to do this?
I have written a separate SizeQtyPrice class with its instance variable in my Item Model. The post request works fine for sending literals but am unsure on sending objects
Note: I am not an experienced coder and completely new to Spring Boot so would really appreciate maybe some background knowledge and pre-requisite info on how to approach or point me in the right direction - (or even tell me if I am too in over my head trying to do this.)
Here is the JSON file I want to send via post request.
{
"name": "Item1",
"description": "Print 1",
"imagePath" : "https://www.tapety-sklep.com/userdata/gfx/abb4fe9b340cb3ff7e72b89a00695b43.jpg",
"detail": "This print is etc.....",
"sizeQtyPrice":[
{
"size": "small",
"qty": 6,
"price": 9.99
},
{
"size": "medium",
"qty": 3,
"price": 15.99
},
{
"size": "large",
"qty": 8,
"price": 20.99
}
]
}
SizeQtyPrice Class (+ getters/setters)
public class SizeQtyPrice {
private String size;
private int qty;
private float price;
public SizeQtyPrice(String size, int qty, float price) {
this.size = size;
this.qty = qty;
this.price = price;
}
Item Model declaring SizeQtyItem[]
public class Item implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String itemCode;
private String name;
private String description;
private String imagePath;
private String detail;
private SizeQtyPrice[] sizeQtyPrice;
Controller Class
#RestController //marks as a controller class
#RequestMapping("/item") //base url
public class ItemResource {
private final ItemService itemService;
#Autowired //injects the service into the constructor
public ItemResource(ItemService itemService) {
this.itemService = itemService;
}
#GetMapping("/all") //get request to retrieve from backend. This is the base URL /item/all
public ResponseEntity<List<Item>> getAllItems() {
List<Item> items = itemService.findAllItems();
return new ResponseEntity<>(items, HttpStatus.OK);
}
#PostMapping("/add")
public ResponseEntity<Item> addItem(#RequestBody Item item) { // JSON format
Item newItem = itemService.addItem(item);
System.out.println(newItem);
return new ResponseEntity<>(newItem, HttpStatus.CREATED);
}
Turns out it was a simple annotation issue in my SizeQtyPrice class. I hadn't annotated the class with #Embeddable
#Embeddable
public class SizeQtyPrice { .....
https://www.baeldung.com/jpa-embedded-embeddable
Edit: I also was not adding a default/empty constructor to my Item class which was giving me the following error:
No Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator.
Adding a default constructor fixed this issue and can now send post requests without issues!
I need to deserialize JSON to java class.
I have JSON like the following:
{
"data": {
"text": "John"
},
"fields":[
{
"id": "testId",
"name": "fieldName",
"options": {
"color": "#000000",
"required": true
}
},
{
"id": "testId",
"name": "fieldName1",
"options": {
"color": "#000000",
"required": false
}
}
]
}
and I need to deserialize this JSON (only "fields" section) to java class like the following:
public class Field {
public final String id;
public final String name;
public final String color;
public final boolean required;
}
and I need to get something like the following:
// The key is the id from field object (it can be the same in the multiple objects.)
Map<String, List<Field>> fields = objectMapper.readValue(json, Map<String, List<Field>>);
How can I do it using Jackson?
As long as jackson doesn't support #JsonWrapped, you have to use the following work around.
First you need to create a custom class which contains the fields:
public class Fields {
public List<Field> fields;
}
Depending on your ObjectMapper configuration you have to add #JsonIgnoreProperties(ignoreUnknown = true) to the Fields class, to ignore any other properties.
Next is that you have to define the nested Options class which is solely used temporarily:
public class Options {
public String color;
public boolean required;
}
And at last add this constructor to your Field class:
#JsonCreator
public Field(#JsonProperty("id") String id, #JsonProperty("name") String name, #JsonProperty("options") Options options){
this.id = id;
this.name = name;
this.color = options.color;
this.required = options.required;
}
The #JsonCreator annotation indicates to jackson that this constructor needs to be used for the deserialization. Also the #JsonProperty annotations are required as arguments to constructors and methods are not preserved in the bytecode
Then you can deserialize your json just like this:
List<Field> fields = objectMapper.readValue(json, Fields.class).fields;