RestTemplate Map JSON array to list of objects - java

I'm having trouble mapping the environments LetakTandaTanganResponseDto in the below JSON response output into a list of LetakTandaTanganResponseDto objects using RestTemplate.
I have a response from URL which looks like:
{
"code": "00",
"desc": "SUCCESS",
"body": [
{
"id": 71,
"createdate": null,
"lx": "104",
"ly": "632",
"page": 1,
"prfKe": 0,
"rx": "260",
"ry": "632",
"ttdKe": 1,
"formatItemId": null,
"formatPdfId": 10
},
{
"id": 72,
"createdate": null,
"lx": "485",
"ly": "629",
"page": 1,
"prfKe": 0,
"rx": "692",
"ry": "629",
"ttdKe": 2,
"formatItemId": null,
"formatPdfId": 10
},
{
"id": 73,
"createdate": null,
"lx": "585",
"ly": "729",
"page": 1,
"prfKe": 0,
"rx": "792",
"ry": "729",
"ttdKe": 3,
"formatItemId": null,
"formatPdfId": 10
}
]
}
RestTemplate code.
ResponseEntity<List<LetakTandaTanganResponseDto>> letakTTDResponse = restTemplate.exchange(uri, HttpMethod.GET, entity, new ParameterizedTypeReference<List<LetakTandaTanganResponseDto>>() {
});
if (letakTTDResponse != null && letakTTDResponse.hasBody()) {
listletakTTD = letakTTDResponse.getBody();
}
return listletakTTD;
Where as, if I happen to use a custom Value object, somethings like:
#Data
#ToString
public class LetakTandaTanganResponseDto {
public String code;
public String desc;
public Body body;
#Data
#ToString
public class Body {
public Long id;
public Integer ttd_ke;
public Integer page;
public String lx;
public String ly;
public String rx;
public String ry;
public String createdate;
public Integer prfKe;
public Long formatItemId;
public Long formatPdfId ;
}
}
Can you help how to the JSON list structure mentioned above can be mapped to an object?

Try changing your response class as per the json response
public class LetakTandaTanganResponseDto {
public String code;
public String desc;
public List<Body> body;
// ...
}
and your response would be
ResponseEntity<LetakTandaTanganResponseDto> letakTTDResponse = restTemplate.exchange(uri, HttpMethod.GET, entity, new ParameterizedTypeReference<LetakTandaTanganResponseDto>() {
});
if (letakTTDResponse != null && letakTTDResponse.hasBody()) {
listletakTTD.setBody( letakTTDResponse.getBody());
}
return listletakTTD;

Related

Add a list of customers to an object in Spring

I have this object that I'm retrieving from antoher microservice.
#Service
public class WebClientService {
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;
});
}
The controller is as follows:
#GetMapping("/getCucoId/{cucoId}")
public Mono<CuCoPerson> getCucoRelationById(#PathVariable Integer cucoId, #RequestHeader(value="Authorization") String GS_AUTH_TOKEN) {
return webClientService.getCuCoPerson(cucoId, GS_AUTH_TOKEN);
}
It returns a list of related customers like this:
{
"id": 1,
"relatedCustomers": [
{
"customerId": "xxx",
"systemId": 999
}
]
}
And now I need to add this list of customers to my PeopleDTO class which is as follows:
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;
}
UPDATE:
Here I'm hardcoding my PeopleDTO just as an example:
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 the result should be something 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
}
]
}
The controller that supposed to retrieve this info is:
#GetMapping("getId/{cucoId}")
public PeopleDTO getFullPeople(#PathVariable Long id) {
return webClientService.createPeople(id);
}
How should I set the customers in here?

rest api - PUT method does not consume the data that GET method fetches

I obtain data with GET method and try to fed them to PUT method.
And I get a bad request error.
But when I edit the JSON as below then everithing works fine.
So why does the first JSON not work?
Controller class:
#RestController
#RequestMapping("/api")
public class FileController {
private final FileService fileService;
private final DocService docService;
private final DraftFileToPresentationConverter draftFileToPresentationConverter;
#Autowired
private DocFileRelationRepository docFileRelationRepository;
#Autowired
public FileController(FileService fileService,
DocService docService,
DraftFileToPresentationConverter draftFileToPresentationConverter) {
this.fileService = fileService;
this.docService = docService;
this.draftFileToPresentationConverter = draftFileToPresentationConverter;
}
#GetMapping("/docs/files/{id}")
public ResponseEntity<FilePresentation> getDraftFile(#PathVariable Long id) {
DraftFile file = fileService.getFile(id);
FilePresentation filePresentation = draftFileToPresentationConverter.convert(file);
return new ResponseEntity<>(filePresentation, HttpStatus.OK);
}
#PutMapping("/docs/files/{id}")
public ResponseEntity<FilePresentation> updateDraftFile(#RequestBody FilePresentation filePresentation) {
fileService.update(draftFileToPresentationConverter.convert(filePresentation));
return new ResponseEntity<>(filePresentation, HttpStatus.OK);
}
DTO:
#Data
public class FilePresentation {
private Long id;
private States state;
private String name;
private String user;
private Date dateUpload;
private Long lenght;
private IdRef document;
private IdRef judgeDoc;
public String getSize()
{
Double result = Double.valueOf(lenght/1024.0/1024.0);
if(result<1)
{
result = Double.valueOf(lenght/1024.0);
if(result<1)
{
return (lenght + " байт");
}
return (result.intValue() + " Кбайт");
}
return (result.intValue() + " Мбайт");
}
}
Troublesome class:
#Data
public class IdRef {
public IdRef(Long id) {
this.id = id;
}
private Long id;
}
JSON that I get with GET method and try to fed to PUT method (and get 400 Bad Request):
{
"id": 21,
"state": "DRAFT",
"name": "DNS-list.tiff",
"user": "JSmith",
"dateUpload": null,
"lenght": 28,
"document": {
"id": 141
},
"judgeDoc": null,
"size": "28 байт"
}
JSON that DOES work
{
"id": 21,
"state": "DRAFT",
"name": "DNS-list.tiff",
"user": "JSmith",
"dateUpload": null,
"lenght": 28,
"document": 141,
"judgeDoc": null,
"size": "28 байт"
}
Try to update RequestBody with #PathVariable
The constructor in IdRef was the reason.
I removed the constructor and it works fine now, my controller consumes the first JSON without errors.

Insert Data to MongoDb Using Panache, Quarkus

I am trying to add data into a mongodb collection using Panache and Quarkus. I am trying to insert a nested document that is like the one below
{
"user_id": 8001,
"name": "John John",
"email":"jj#justiceleague.com",
"entity":6,
"business_unit": 3,
"contact_person":"Bats Nopower",
"contact_person_phone":"+25472000001",
"verification_data":{
"national_id": "987643",
"tax_pin":"A0GYE09753ew",
"driving_licence":"6473412"
},
"country":"KE"
}
However when I insert the data this is how it looks like
{
"_id": {
"$oid": "609472b1b410cd46bc3bc674"
},
"business_unit": 3,
"country": "KE",
"created_date": {
"$date": "2021-05-07T01:50:25.341Z"
},
"email": "jj#justiceleague.com",
"entity": 6,
"name": "John John",
"user_id": 8001,
"verification_data": {
"verification_data": {
"national_id": "987643",
"tax_pin": "A0GYE09753ew",
"driving_licence": "6473412"
}
}
}
verification_data is nested inside another verification_data. Not sure what am missing
This is how my data class looks like
#MongoEntity(collection="basic_info")
public class BasicInfo extends PanacheMongoEntity {
#SerializedName("user_id")
#BsonProperty("user_id")
public Integer userId;
public String name;
public String email;
public Integer entity;
#BsonProperty("business_unit")
public Integer businessUnit;
#BsonProperty("contact_person")
public String contactPerson;
#BsonProperty("contact_person_phone")
public String contactPhone;
#BsonProperty("created_date")
public LocalDateTime createdDate;
public String country;
#BsonProperty("verification_data")
public Object verificationData;
//getters and setters
}
This is how I persist the data
public void addBasicInfo(BasicInfo basicInfo) {
BasicInfo initialData = new BasicInfo();
initialData.setUserId(basicInfo.getUserId());
initialData.setName(basicInfo.getName());
initialData.setEmail(basicInfo.getEmail());
initialData.setEntity(basicInfo.getEntity());
initialData.setBusinessUnit(basicInfo.getBusinessUnit());
initialData.setVerificationData(basicInfo.getVerificationData());
initialData.setCountry(basicInfo.getCountry());
initialData.setCreatedDate(LocalDateTime.now());
initialData.persist();
}
This is how my codec looks like
public class ObjectCodec implements Codec<Object> {
private final Codec<Document> documentCodec;
public ObjectCodec() {
this.documentCodec = MongoClientSettings.getDefaultCodecRegistry().get(Document.class);
}
#Override
public void encode(BsonWriter writer, Object object, EncoderContext encoderContext) {
Document doc = new Document();
doc.put("verification_data", object);
documentCodec.encode(writer, doc, encoderContext);
}
#Override
public Class<Object> getEncoderClass() {
return Object.class;
}
//...
}
Note: I do not know how verification_data will look like before hand that is why am treating it as an Object.

Processing complex JSON list to POJO

I have a json response from an external API in below format.But I am not sure how to convert this to a POJO to get all these values separately later in the application
{
"count": 1,
"item_list": [
{
"property_value_map": {
"Data": {
"content_type": "image/jpeg",
"data": "ZJRgABAAEASABIAAD//gAfTEVBRCBUZWNobm9sb2dpZXMgSW5jLiBWMS"
},
"DataType": 0,
"LastChanged": "2015-12-11T17:21:15+00:00",
"ObjectType": 1,
"PersonID": 1384
}
}
],
"page_number": 1,
"page_size": 20,
"total_items": 1,
"total_pages": 1,
"type_name": "Lnl_MultimediaObject",
"version": "1.0"
}
I created a POJO as below and its converting this JSON. But the issue is I dont know how to get the value for "data" from above JSON as my item_list is Object
public class GetInstancesResponseVO {
private int count;
private List<Object> item_list;
private int page_number;
private int page_size;
private int total_items;
private int total_pages;
private String type_name;
private String version;
public GetInstancesResponseVO() {}
/***Getters Setters **/
}
UPDATE
Tried with a pojo as suggested by Jaume Morón i Tarrasa
public class GetInstancesResponseVO {
private int count;
private List<PropertyValueMap> item_list;
private int page_number;
private int page_size;
private int total_items;
private int total_pages;
private String type_name;
private String version;
/***CONSTRUCTOR, SETTERS, GETTERS***/
}
But I am getting null . Here is my PropertyValueMap POJO;
public class PropertyValueMap {
private MyData Data;
private int DataType;
private String LastChanged;
private String ObjectType;
private String PersonID;
public PropertyValueMap() {}
/***GETTERS,SETTERS**/
}
And the Data POJO;
public class MyData implements Serializable{
private String content_type;
private String data;
public MyData() {}
/***GETTERS, SETTERS**/
}
I tried Data as String in PropertValueMap POJO and in either way I am getting null as below;
{
"count": 1,
"item_list": [
{
"objectType": null,
"data": null,
"personID": null,
"lastChanged": null,
"dataType": 0
}
],
"page_number": 1,
"page_size": 20,
"total_items": 1,
"total_pages": 1,
"type_name": "Lnl_MultimediaObject",
"property_value_map": null,
"version": "1.0"
}
And also the JSON response does not look like right as its missing "property_value_map". A help would be greatly appreciated as I am going to waste yet another day for it.

How to convert JSON objects to POJO from Gson

I am trying to convert JSON objects to POJO's with GSON.
JSON String
[
{
"automation_project": {
"user_id": null,
"name": "Untitled Project",
"updated_at": "2015-06-16T19:39:42Z",
"group_id": 764496,
"created_at": "2014-11-23T01:01:59Z",
"id": 16214
}
},
{
"automation_project": {
"user_id": null,
"name": "newintropage",
"updated_at": "2015-06-16T21:20:47Z",
"group_id": 764496,
"created_at": "2015-06-16T20:39:04Z",
"id": 29501
}
}
]
The AutomationProjectsList class used with GSON
public class AutomationProjectsList {
private List<AutomationProject> automationProject = new ArrayList<AutomationProject>();
public List<AutomationProject> getAutomationProject() {
return automationProject;
}
public void setAutomationProject(List<AutomationProject> automationProject) {
this.automationProject = automationProject;
}
#Override
public String toString() {
return "AutomationProjectsList [automationProject=" + automationProject
+ "]";
}}
Automation Project POJO
public class AutomationProject {
private Object userId;
private Integer groupId;
private Integer id;
private String name;
private String updatedAt;
private String createdAt;
public Object getUserId() {
return userId;
}
public void setUserId(Object userId) {
this.userId = userId;
}
public Integer getGroupId() {
return groupId;
}
public void setGroupId(Integer groupId) {
this.groupId = groupId;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(String updatedAt) {
this.updatedAt = updatedAt;
}
public String getCreatedAt() {
return createdAt;
}
public void setCreatedAt(String createdAt) {
this.createdAt = createdAt;
}}
The code I'm using
JSONArray jsonArray = new JSONArray(response.getEntity(String.class));
for(int i = 0; i < jsonArray.length(); i++){
if(jsonArray.get(i) instanceof JSONObject){
JSONObject jsnObj = (JSONObject)jsonArray.get(i);
AutomationProjectsList obj = new Gson().fromJson(jsnObj.toString(), AutomationProjectsList.class);
System.out.println(obj.getAutomationProject().get(0).getId());
}
}
But it gives an exception :
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:653)
at java.util.ArrayList.get(ArrayList.java:429)
at br.usp.icmc.teste.ConnectionRestClient.getBrowserStackProjects(ConnectionRestClient.java:74)
at br.usp.icmc.teste.TestePrincipal.main(TestePrincipal.java:9)
Why am I receiving an IndexOutOfBoundsException exception? Where am I wrong?
Your class or your JSON are incorrect. I'd suggest your JSON is.
A JSON matching your POJO class would be:
{
"automationProjects":[
{
"user_id": null,
"name": "Untitled Project",
"updated_at": "2015-06-16T19:39:42Z",
"group_id": 764496,
"created_at": "2014-11-23T01:01:59Z",
"id": 16214
},
{
"user_id": null,
"name": "newintropage",
"updated_at": "2015-06-16T21:20:47Z",
"group_id": 764496,
"created_at": "2015-06-16T20:39:04Z",
"id": 29501
}
]
}
Notice I used the name automationProjects for the list as it makes more sense, so your class would be:
public class AutomationProjectsList {
private List<AutomationProject> automationProjects = new ArrayList<AutomationProject>();
public List<AutomationProject> getAutomationProjects() {
return automationProjects;
}
public void setAutomationProjects(List<AutomationProject> automationProjects) {
this.automationProjects = automationProjects;
}
#Override
public String toString() {
return "AutomationProjectsList [automationProject=" + automationProject
+ "]";
}
}
And finally to convert JSON to AutomationProjectsList object:
AutomationProjectsList projectsList = new Gson().fromJson(jsonArray.toString(), AutomationProjectsList.class);
Then if you want to log each project:
for(AutomationProject project : projectsList.automationProjects){
System.out.println(porject.getId());
}
In conclusion, your code seems to have the fallowing issues:
Do you have a list of lists or just a single list of projects? If the list is just one, why do you iterate jsonArray like its sub-objects are lists themselves?
If you model your class correctly on the JSON then you don't need to iterate the JSON to obtain your objects
The JSON you posted is quite weird and uneasy to use with Gson, is it a requirement or can you edit it as you please?
Hope this helps
EDIT
Since you stated you cannot change the JSON you get, then it gets a little more complex, but everything is up to modelling the classes on the JSON format. So let's start form this JSON:
[
{
"automation_project": {
"user_id": null,
"name": "Untitled Project",
"updated_at": "2015-06-16T19:39:42Z",
"group_id": 764496,
"created_at": "2014-11-23T01:01:59Z",
"id": 16214
}
},
{
"automation_project": {
"user_id": null,
"name": "newintropage",
"updated_at": "2015-06-16T21:20:47Z",
"group_id": 764496,
"created_at": "2015-06-16T20:39:04Z",
"id": 29501
}
}
]
Now, this is quite nasty, but let's see what we have here: we have an unnamed array of objects with a single attribute "automationProject" which is our actual AutomationProject Object. So in terms of structure, it is a list of objects which wrap an actual AutomationProject.
Thus you'll need to get rid of your AutomationProjectList and change it with the more meaningful AutomationProjectWrapper looking as fallows:
public class AutomationProjectsWrapper {
private AutomationProject automation_project = new AutomationProject();
public AutomationProject getAutomationProject() {
return automation_project;
}
public void setAutomationProject(AutomationProject automationProject) {
this.automation_project = automationProject;
}
#Override
public String toString() {
return "AutomationProjectsList [automationProject=" + automation_project
+ "]";
}
}
See this class is equivalent to the JSON Object:
{
"automation_project": {
"user_id": null,
"name": "Untitled Project",
"updated_at": "2015-06-16T19:39:42Z",
"group_id": 764496,
"created_at": "2014-11-23T01:01:59Z",
"id": 16214
}
}
Finally you'll have an array of such wrapper objects as your jsonArray so you can write:
AutomationProjectWrapper[] projectsList = new Gson().fromJson(jsonArray.toString(), AutomationProjectWrapper[].class);
Then to log your objects:
for(AutomationProjectWrapper wrapper : projectsList){
System.out.println(wrapper.getAutomationProject().getId());
}
EDIT 2
Sorry for the mistake, in AutomationProjectWrapper class the AutomationProject field should be named automation_project.
Fixed in code above.
According to your JSON String the value you are trying to access is :
jsonString[i].automation_project.user_id
In your code you have: obj.getAutomationProject().get(0).getId()
I think is should be: obj[i].getAutomationProject().getId()

Categories