Including nested objects in the JSON of a Spring Boot application - java

Can anyone guide me on how to nest the JSON object Activation under the JSON object Data.
See my JSON below:
{
"status": "Success",
"DATA": {
"aid": "0",
"app": "OASIS_EDGE",
"actkey": "STAR2020",
"expiredate": "2025-08-05 04:40:28.0",
"partner": "X",
"nsp": "NAD"
}
}
The JSON I actually expect:
{
"STATUS": "SUCCESS",
"DATA": {
"ACTIVATION": {
"aid": "0",
"app": "OASIS_EDGE",
"actkey": "STAR2020",
"expiredate": "2025-08-05 04:40:28.0",
"partner": "X",
"nsp": "NAD"
}
}
}
Here is my ActivationResponse.java class responsible for creating the JSON:
public class ActivationResponse {
private String Status;
public String getStatus()
{
return Status;
}
public void setStatus(String Status) {
this.Status = Status;
}
#JsonProperty("DATA")
private ActivationModel activationData;
public ActivationModel getActivationData() {
return activationData;
}
public void setActivationData(ActivationModel activationData2) {
this.activationData = activationData2;
}
}

Since you want activation under data, you need a class data with a field for activation, like the example below.
class MyJson {
private String Status;
#JsonProperty("DATA")
private DataModel data;
};
class DataModel {
#JsonProperty("ACTIVATION")
private ActivationModel activation;
};

Use JsonNode from com.fasterxml.jackson.databind.JsonNode à la:
import com.fasterxml.jackson.databind.JsonNode;
public class ActivationResponse {
private String Status;
private JsonNode activationData;
public String getStatus() return Status;
public void setStatus(String Status) this.Status = Status;
public ActivationModel getActivationData() return activationData;
public void setActivationData(ActivationModel activationData2) {
activationData = activationData2;
}
}
Use the good 'ol Map from java.util.Map like so:
import java.util.Map;
public class ActivationResponse {
private String Status;
private Map<String, Object> activationData;
public String getStatus() return Status;
public void setStatus(String Status) this.Status = Status;
public ActivationModel getActivationData() return activationData;
public void setActivationData(ActivationModel activationData2) {
activationData = activationData2;
}
}
I shamelessly borrowed from this tutorial (no affiliations)!

Related

How to handle Json Array and Json Object same time in Retrofit Andorid

I am new to Android. When the response is a success, I get a JSON Object and when it is a failure I get an empty JSON array.
I have created a POJO class for the same, but I'm getting the exception below:
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException:
Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 5 column 14 path
$.data
When the API response is a success, I get the response below:
{
"status": "S",
"code": "000",
"description": "OTP Sent Successfully",
"data": {
"ProcessId": "39a71-6d5c-4ae1-1415e63"
}
}
When the response is a failure, I get the response below:
{
"status": "F",
"code": "002",
"description": "Customer with Mobile already Exists",
"data": []
}
My POJO Class:
public class SendOtpAPI {
#SerializedName("status")
#Expose
private String status;
#SerializedName("code")
#Expose
private String code;
#SerializedName("description")
#Expose
private String description;
#SerializedName("data")
#Nullable
#Expose
private Data data;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Data getData() {
return data;
}
public void setData(Data data) {
this.data = data;
}
}
POJO Data Class:
public class Data {
#SerializedName("ProcessId")
#Expose
private String processId;
public String getProcessId() {
return processId;
}
public void setProcessId(String processId) {
this.processId = processId;
}
}
Retrofit API Call:
#FormUrlEncoded
#POST("https://dev2.test/otp")
Call<SendOtpAPI> sendOtpRegister(
#Field("operation")String operation,
#Field("mobile")String mobile
);
How can I handle this?
Modify your Model class- the exception itself says the solution
Check your API in Postman your response contains Array I think, And You have declared Data as an object in SendOtpAPI model class. check the below code -
Change Data class into an array in SendOtpAPI model class
private Data data; --> private ArrayList<Data> dataList;

How can I parse object inside array using retrofit

[
{
"login": "mojombo",
"id": 1,
"node_id": "MDQ6VXNlcjE=",
"avatar_url": "https://avatars0.githubusercontent.com/u/1?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/mojombo",
"html_url": "https://github.com/mojombo",
"followers_url": "https://api.github.com/users/mojombo/followers",
"following_url": "https://api.github.com/users/mojombo/following{/other_user}",
"gists_url": "https://api.github.com/users/mojombo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/mojombo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/mojombo/subscriptions",
"organizations_url": "https://api.github.com/users/mojombo/orgs",
"repos_url": "https://api.github.com/users/mojombo/repos",
"events_url": "https://api.github.com/users/mojombo/events{/privacy}",
"received_events_url": "https://api.github.com/users/mojombo/received_events",
"type": "User",
"site_admin": false
}
]
Json: https://api.github.com/users
This is URL of an API... how can i parse this object to fetch the data using retrofit?
Here is the example on how to fetch JSON object with array using retrofit. I believe you won't have troubles changing it to work with your data.
Example.java
public class Example {
#SerializedName("PnrNumber")
#Expose
private String pnrNumber;
#SerializedName("Status")
#Expose
private String status;
#SerializedName("ResponseCode")
#Expose
private String responseCode;
#SerializedName("TrainNumber")
#Expose
private String trainNumber;
#SerializedName("TrainName")
#Expose
private String trainName;
#SerializedName("JourneyClass")
#Expose
private String journeyClass;
#SerializedName("ChatPrepared")
#Expose
private String chatPrepared;
#SerializedName("From")
#Expose
private String from;
#SerializedName("To")
#Expose
private String to;
#SerializedName("JourneyDate")
#Expose
private String journeyDate;
#SerializedName("Passangers")
#Expose
private List<Passanger> passangers = null;
public String getPnrNumber() {
return pnrNumber;
}
public void setPnrNumber(String pnrNumber) {
this.pnrNumber = pnrNumber;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getResponseCode() {
return responseCode;
}
public void setResponseCode(String responseCode) {
this.responseCode = responseCode;
}
public String getTrainNumber() {
return trainNumber;
}
public void setTrainNumber(String trainNumber) {
this.trainNumber = trainNumber;
}
public String getTrainName() {
return trainName;
}
public void setTrainName(String trainName) {
this.trainName = trainName;
}
public String getJourneyClass() {
return journeyClass;
}
public void setJourneyClass(String journeyClass) {
this.journeyClass = journeyClass;
}
public String getChatPrepared() {
return chatPrepared;
}
public void setChatPrepared(String chatPrepared) {
this.chatPrepared = chatPrepared;
}
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
public String getJourneyDate() {
return journeyDate;
}
public void setJourneyDate(String journeyDate) {
this.journeyDate = journeyDate;
}
public List<Passanger> getPassangers() {
return passangers;
}
public void setPassangers(List<Passanger> passangers) {
this.passangers = passangers;
}
}
Passanger.Java
public class Passanger {
#SerializedName("Passenger")
#Expose
private String passenger;
#SerializedName("BookingStatus")
#Expose
private String bookingStatus;
#SerializedName("CurrentStatus")
#Expose
private String currentStatus;
public String getPassenger() {
return passenger;
}
public void setPassenger(String passenger) {
this.passenger = passenger;
}
public String getBookingStatus() {
return bookingStatus;
}
public void setBookingStatus(String bookingStatus) {
this.bookingStatus = bookingStatus;
}
public String getCurrentStatus() {
return currentStatus;
}
public void setCurrentStatus(String currentStatus) {
this.currentStatus = currentStatus;
}
}
Here are the classes which are generated from the Response which you have provided in the question.
You can use this link to generate the POJO class for JSON response.
JSON TO POJO
Add this gradle:
implementation 'com.google.code.gson:gson:2.8.2'
Init the Gson buildr:
private Gson gson;
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setDateFormat("M/d/yy hh:mm a");
gson = gsonBuilder.create();
Parse the JSON using GSON
gson.fromJson(jsonObject.getJSONObject("data").toString(), Example.class);
These are the basic steps to parse the JSON using GSON.
For more information you can refer to the below article:
Parsing JSON on Android using GSON
Or Check the GSON official GitHub Repository
GSON

how can I work with wrapped data using moshi, retrofit and java?

I'm working with an API where all data are wrapped in a custom object (see below), so I cannot use moshi to convert the retrofit body direct to my models. What is the best way to work with moshi in this case?
#COLLECTIONS ENDPOINT
{
"status": 200,
"data": [
{
"id": 28122,
"name": "Abandonei",
"counts": {
"books": 3
}
},
{
"id": 21091,
"name": "Lendo",
"counts": {
"books": 6
}
},
],
"errors": [],
"pagination": {
"after": 2,
"hasNextPage": true
}
}
The same json structure is used in all api endpoints, the default fields are:
{
"status": 200,
"data": [],
"errors": [],
"pagination": {
"after": 1,
"hasNextPage": true
}
}
My Collection model:
public class BookCollection {
public long id;
public String name;
public ArrayList<Book> books;
public BookCollection(long id, String name) {
this.id = id;
this.name = name;
}
}
To avoid create a parent class to each model, I have implemented a way to use a class that receive a generic type.
To put this to work I've changed the Moshi class to Gson.
My model:
public class BookCollection {
public long id;
public String name;
public ArrayList<Book> books;
public BookCollection(long id, String name) {
this.id = id;
this.name = name;
}
}
The wrapper class used to unwrap the json data:
public class ApiWrapper<T> {
public final int status;
public final T data;
public final List<ApiError> errors = new ArrayList<>();
public ApiWrapper(int status, T data, List<ApiError> errors) {
this.status = status;
this.data = data;
this.errors.addAll(errors);
}
}
The Errors class, referenced in the class above:
public class ApiError {
public int code;
public String message;
public String error;
}
Usage:
public interface NetAPI {
#GET("me/collections")
Call<ResponseBody> getCollections(#Header("Authorization") String auth);
}
public class CollectionViewModel extends ViewModel {
private final MutableLiveData<List<Collection>> collections = new MutableLiveData<>();
private final MutableLiveData<Boolean> loading = new MutableLiveData<>();
private final MutableLiveData<Boolean> collectionError = new MutableLiveData<>();
private Call<ResponseBody> call;
private void fetchCollections() {
loading.setValue(true);
call = Api.getInstance().getCollections(TOKEN);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
collectionError.setValue(false);
//THE SECRET
Gson gson = new Gson();
ApiWrapper<List<Collection>> apiResponse = null;
apiResponse = gson.fromJson(response.body().string(), new TypeToken<ApiWrapper<List<Collection>>>(){}.getType());
collections.setValue(apiResponse.data);
loading.setValue(false);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.e(getClass().getSimpleName(), "Error loading data", t);
collectionError.setValue(true);
loading.setValue(false);
}
});
}
}
At this way I can reuse my ApiWrapper class to any model (Books, Users, Login, etc).
Thanks.
You will need to setup gson/moshi to use your classes that you have created for the json to object mapping. Here is an example of what those java classes would look like. You can use data classes in kotlin as well. For moshi, you will have to create the adapter to help with the json to object mapping.
publci class CollectionResponse {
public int status;
public List<BookCollection> data;
public List<Error> errors;
public Pagination pagination;
}
public class Pagination {
public int after;
public boolean hasNextPage;
}
public class BookCollection {
public long id;
public String name;
public Count counts;
}
public Count {
public int books;
}
public class Error {
}

Get Json Array in Post Retrofit

I have a problem when I want to retrieve an array from a post response
this is my post
{
"user_email": "xxxx#gmail.com",
"user_password": "12345"
}
and this is my post response , I want get the token value
{
"status": true,
"code": 200,
"message": "Request Succeded: Login success",
"data": [
{
"token": "bsWIVXTLuud2ZbdnUvI8037fT7D0t7MTvusBrNjskah"
}
]
}
this is my model LoginModel.java
#SerializedName("data")
#Expose
private Data data ;
public Data getData() {
return data;
}
public void setData (Data data) {
this.data = data;
}
public LoginModel(String user_email, String user_password) {
this.user_email = user_email;
this.user_password = user_password;
}
Data.java
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
there code I'm tried before ,the text view show nothing
LoginModel loginModelresponse = response.body();
String token = loginModelresponse.getData().getToken();
textView.setText(token);
I want get the token from my post response.
Your data value is an array of tokens, not an object itself
Create a Token class with a token String field, then replace the Data class like so
#SerializedName("data")
#Expose
private List<Token> data ;
To get the token, you must iterate the list
Try to change your LoginModel class, because your response data object is Array type
public class LoginModel {
#SerializedName("status")
#Expose
private Boolean status;
#SerializedName("code")
#Expose
private Integer code;
#SerializedName("message")
#Expose
private String message;
#SerializedName("data")
#Expose
private List<Data> data = null;
public Boolean getStatus() {
return status;
}
public void setStatus(Boolean status) {
this.status = status;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public List<Data> getData() {
return data;
}
public void setData(List<Data> data) {
this.data = data;
}
}
use this site to generate a correct response class in java
public class Tokens implements Serializable
{
#SerializedName("token")
#Expose
private String token;
private final static long serialVersionUID = 1577013820593763604L;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}
// -----------------------------------com.example.Response.java-----------
package com.example;
import java.io.Serializable;
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Response implements Serializable
{
#SerializedName("status")
#Expose
private boolean status;
#SerializedName("code")
#Expose
private long code;
#SerializedName("message")
#Expose
private String message;
#SerializedName("data")
#Expose
private List<Tokens> data = null;
private final static long serialVersionUID = -3002290394951662690L;
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public long getCode() {
return code;
}
public void setCode(long code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public List<Tokens> getData() {
return data;
}
public void setData(List<Tokens> data) {
this.data = data;
}
}

Rest response bean extends Map

In a spring rest application context, i'm trying to create a generic response bean.
The purpose is to avoid to create a specific bean for each method.
I'd like to use standard fields, like status and message, by binding various properties to a map.
Consider the following example :
public class ResponseRestDefault extends HashMap {
private String status;
private String message;
public ResponseRestDefault() {
}
public void addParam(String key, String value) {
this.put(key, value);
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
Usage
#RequestMapping(value = "response", method = RequestMethod.GET)
public ResponseEntity<ResponseRestDefault> response() {
ResponseRestDefault response = new ResponseRestDefault();
response.setStatus("success");
response.setMessage("ok");
response.addParam("test", "value");
return ResponseEntity.ok(response);
}
Json result :
{
"test": "value"
}
Does the json result could contain map fields and class properties ?
You need to modify your response class. Make sure you have the getter and setter methods for map.
public class ResponseRestDefault {
private String status;
private String message;
private Map<String, String> map = new HashMap<>();
public ResponseRestDefault() {
}
public void setMap(String key, String value) {
map.put(key, value);
}
public Map<String, String> getMap()
{
return map;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
You will get response in below format :
{
"status": "success",
"message": "ok",
"map": {
"test": "value"
}
}

Categories

Resources