How to get an arrayJSON in webService Rest? - java

I am developing a WEb Service Rest in java, netbeans.
This is the JSON I want to receive:
{
"ticket":"2132158645161654561651616",
"avaliacoes":[
{
"id":1,
"nome":"Atendimento",
"nota":5,
"observacoes":"testeTEste"
},
{
"id":2,
"nome":"Atendimento",
"nota":5,
"observacoes":"testeTEste"
}
]
}
Reception Class
#PUT
#Consumes(MediaType.APPLICATION_JSON)
#Path("venda/enviardados")
public String postVenda(#QueryParam("key") String key, #QueryParam("serial") String serial, VendaAvaliacao va) {
...
}
Entity Classes
public class VendaAvaliacao {
private int id;
private String ticket;
//private List<VendaAvaliacaoInner> avaliacoes = new ArrayList<>(); //I've tried it too
private VendaAvaliacaoInner[] teste;
}
public class VendaAvaliacaoInner {
private int id;
private String nome;
private int nota;
private String observacao;
}
The ticket is received and populated, but array = null.
I've read other similar topics but they did not help .... how can I do?
https://pt.stackoverflow.com/questions/6046/convers%C3%A3o-de-string-json-para-objeto-java?rq=1
https://pt.stackoverflow.com/questions/159725/receber-valor-de-array-json-para-string-java
https://pt.stackoverflow.com/questions/290759/como-obter-objetos-de-um-array-de-json-usando-jsonarray-no-java

Maybe the service REST you are consuming don't populate the data in the array.
As an advice i would work with List<T> rather than T[]
Also i see that you are mapping 3 properties in you object but the id property don't exist in raw JSON isn't it ?

Related

How to get different parameters for different APIs like mentioned below

I need to get different parameters in response for 2 different APIs getAlland getbyID.
Now I get the same result -second json for both APIs.
I want to get 1st json in reponse of api getALL without the one-to-many relation and
I want to get 2nd json in reponse of api getbyid with one-to-many relation
First JSON Response:
{
"id":2,
"itemName":"book",
}
Second JSON Response:
{
"id":2,
"itemName":"book",
"owner":
{
"id":1,
"name":"John"
}
}
User Class
public class User {
public int id;
public String name;
#JsonBackReference
public List<Item> userItems;
}
Item class
public class Item {
public int id;
public String itemName;
#JsonManagedReference
public User owner;
}
can anyone help in this?
My suggestion is to make item class just for data transfer like:
public class ItemDTO {
public int id;
public String itemName;
}
Then in your controller you can do something like that:
#GetMapping('/get-all')
public ResponseEntity<ItemDTO> getAll() {
//get Item object
Item item = //e.g database call
ItemDTO itemDTO = new ItemDTO(item.id, item.name);
return ResponseEntity.ok(itemDTO);
}
#GetMapping('/get-by-id/{id}')
public ResponseEntity<Item> getAll(#PathVariable Integer id) {
Item item = //e.g get item by id
return ResponseEntity.ok(item);
}

Parse two different API response using Retrofit 2 in Android

I am facing a problem while parsing API response using Retrofit 2.
The API's are already in production and I cannot request a change in API.
Following are two different responses I am getting from server
Success response:
{
"status":0,
"empId":121,
"message":"Data available",
"data":{
"name":"Sam",
"designation": "Software Engineer",
"mob": "1255565456"
}
}
Failure response
{
"status":10,
"empId":121,
"message":"No data available",
"data":""
}
Parsing Classes
class Response{
public int status;
public String message;
public int empId;
public Student data;
}
class Student{
public String name;
public String designation;
public String mob;
}
I am able to parse the success response. But getting the following exception for the failure case.
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING
try this ,
Object getrow = null;
try {
getrow = this.// your object
LinkedTreeMap<Object, Object> tree = (LinkedTreeMap) getrow;
String name = tree.get(<your body>).toString()
} catch (Exception e) {
e.printStackTrace();
}
The way that you can handle this situation is by treating 'data' as a generic object rather than as a String or 'Student'.
p̶u̶b̶l̶i̶c̶ ̶S̶t̶u̶d̶e̶n̶t̶ ̶d̶a̶t̶a̶;̶
public Object data;
While Using data add a check like this
if(data instanceof String){
String parsedData=data.toString();
}else{
Student parsedData= (Student) data;
}
Make Student as an inner class or Response class. and Retrofit will parse the response and will give you the object.
class Response
{
public int status;
public String message;
public int empId;
public Student data;
Class Data
{
public String name;
public String designation;
public String mob;
}
}

Why are some of the variables in POJO equal to null after converting JSON RESTful Webservice?

I am consuming a RESTful webservice that returns a JSON payload. I can successfully consume the RESTful webservice and manage to populate some of the POJO attributes with JSON data. However, some other attributes are null when they are supposed to contain a value. How can I ensure that there are no more nulls?
I have defined 4 POJO classes. I have so far debugged by systematically by testing the variables for each class. This is using Springboot 2.2.0 and Jackson-databind.
The JSON schema I am trying to consume:
{
"items":[
{
"timestamp":"2019-09-18T16:42:54.203Z",
"carpark_data":[
{
"total_lots":"string",
"lot_type":"string",
"lots_available":"string"
}
]
}
]
}
For the above, I defined 4 classes:
public class Response {
#JsonProperty
private List<items> i;
#JsonIgnoreProperties(ignoreUnknown = true)
public class items {
private String timestamp;
private List<carpark_data> cpd;
#JsonIgnoreProperties(ignoreUnknown = true)
public class carpark_data {
private List<carpark_info> cpi;
private String carpark_number;
private String update_datetime;
#JsonIgnoreProperties(ignoreUnknown = true)
public class carpark_info {
private int total_lots;
private String lot_type;
private int lots_available;
When I run the below in Spring boot Main: I get null. Is my POJO modeling OK?
Response resp = restTemplate.getForObject("")
c = resp.getItems().get(0).getCarpark_data().get(0);
log.info("The last update time for the car park data = " +
c.getUpdateDatetime());
Your model does not fit to JSON payload. If we assume that JSON payload has a structure like below:
{
"items": [
{
"timestamp": "2019-09-18T16:42:54.203Z",
"carpark_data": [
{
"total_lots": "1000",
"lot_type": "string",
"lots_available": "800"
}
]
}
]
}
We can deserialise it as below:
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.util.List;
public class JsonApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
ObjectMapper mapper = new ObjectMapper();
Response response = mapper.readValue(jsonFile, Response.class);
System.out.println(response.getItems().get(0).getData().get(0));
}
}
class Response {
private List<Item> items;
//getters, setters, toString
}
class Item {
private String timestamp;
#JsonProperty("carpark_data")
private List<CarParkInfo> data;
//getters, setters, toString
}
class CarParkInfo {
#JsonProperty("total_lots")
private int totalLots;
#JsonProperty("lot_type")
private String lotType;
#JsonProperty("lots_available")
private int lotsAvailable;
//getters, setters, toString
}
Above code prints:
CarParkInfo{totalLots=1000, lotType='string', lotsAvailable=800}
Hope you find the solution.
It is in POJO, you need to check the fieldName and object structure.
Seeing the Json above, your response model returns list of items and in each item you have list of carpark_data. So, basic modelling should be like this. And you can include respective setter and getter.
public class Response {
#JsonProperty
private List<items> items;
#JsonIgnoreProperties(ignoreUnknown = true)
public class items {
private String timestamp;
private List<carpark_data> carpark_data;
#JsonIgnoreProperties(ignoreUnknown = true)
public class carpark_data {
private int total_lots;
private String lot_type;
private int lots_available;
}
You need to have fields name in POJO class same in the Json response or you can set JsonProperty for that field. Like this
#JsonProperty("items")
private List<items> i;
#JsonProperty("carpark_data")
private List<carpark_data> cpd;

Create a Post method to save an object with multiples id

I have in my controller:
#RestController
public class OneTwoController {
private OnTwoService _service;
//... more code
#PostMapping("/api/one-two")
#CrossOrigin
public ResponseEntity<ServiceResponse> save(#RequestBody OneTwo model) {
return ResponseEntity.ok().body( _service.Save(model));
}
In my entity:
#Entity(name = "OneTwo")
#Where (clause = "deleted='false'")
public class OneTwo{
#EmbeddedId
private OneTwoKey_id;
public OneTwo(OneTwoKey id) {
this._id = id;
}
#JsonProperty("oneTwo")
public void setId(OneTwoKey value) {
this._id = value;
}
The OneTwoKey class:
public class OneTwoKey implements Serializable {
#Column(name = "OneID")
private int _oneID;
#Column(name = "TwoID")
private int _twoID;
public OneTwoKey(int oneID, int twoID) {
this._oneID = oneID;
this._twoID = twoID;
}
}
The json that I send to the Rest API:
{
"oneTwo": {
"oneID": 83,
"twoID": 69
},
"deleted": true
}
The issue is that both ids arrive null, so the service can't do the insert on the DB.
How can I deal with those cases when the ids are more than one?
Try adding setters in the OneTwoKey class to make it easier for the JSON deserializer:
#JsonProperty("oneID")
public void setOneID(int oneID) {
this._oneID = oneID;
}
#JsonProperty("twoID")
public void setTwoID(int twoID) {
this._twoID = twoID;
}
Another solution is to create a DTO, use it to receive the data in the controller and then convert it to your entity:
public class OneTwoDTO {
private Map<String, Int> oneTwo;
private boolean deleted;
// setters & getters
}
Simply what you can do is instead of using
public ResponseEntity<ServiceResponse> save(#RequestBody OneTwo model) {
you can use
public ResponseEntity<ServiceResponse> save(#RequestBody String model) {
Now convert the String to json and get all the key value pairs, it would be easier if you have dynamic number of variables and you want to capture them all.
or you can use tools like jsonschema2pojo whick take a json schema and generate a pojo. In the json schema if you set
"additionalProperties": true
you can capture all the values.
Could you make sure the problem is not because of case sensitivity?
Lower case the column names. Also could you use public access on those variables as well? These are my initial guesses as to why the payload is not being binded correctly.
public class OneTwoKey implements Serializable {
#Column(name = "oneID")
public int _oneID;
#Column(name = "twoID")
public int _twoID;

flexjson.JSONException Don't know how to bind

My android application use flexjson library to deserialize json data string received from server via RESTfull webservice. But when deserialize i get error.
flexjson.JSONException: [ data.status ]: Don't know how to bind Clock_in into class wfa.com.tma.wfa.type.TimeClockStatus. You might need to use an ObjectFactory instead of a plain class.
this is my String
{
"data":
{
"todayShift":
{
"startTime":"1970-01-01T13:30:00Z",
"endTime":"1970-01-02T00:00:00Z",
"office":
{
"id":1,"name":"Location Test 1"
}
},
"currentTime":"2017-10-12T07:47:11Z",
"status":"Clock_in",
"latestTime":"2017-10-12T07:46:13Z",
"latestOffice":{"id":1,"name":"Location Test 1"}},
"meta":{"type":"TimeClockDto"}
}
the DTO of this String
public class TimeClockDto implements Serializable
{
private static final long serialVersionUID = 1L;
private TodayShiftDto todayShift;
private String currentTime;
private TimeClockStatus status;
private String latestTime;
private BaseLocationDto latestOffice;
public TimeClockDto(TodayShiftDto todayShift, String currentTime,
TimeClockStatus status, String latestClockInTime,
BaseLocationDto latestOffice)
{
this.todayShift = todayShift;
this.currentTime = currentTime;
this.status = status;
this.latestTime = latestClockInTime;
this.latestOffice = latestOffice;
}
//getter, setter
}
`and the deserialize code
and the enum class
public enum TimeClockStatus
{
Clock_in, Clock_out;
}
I have solve this problem by using EnumObjectFactory
TimeClockDto result = new JSONDeserializer<TimeClockDto>
.use("data", TimeClockDto.class)
.use("data.todayShift", TodayShiftDto.class)
.use("data.status", new EnumObjectFactory())
.use("data.latestOffice", BaseLocationDto.class)
.deserialize(param.getResult(),TimeClockDto.class);

Categories