Retrofit: Json parser according to response - java

I have a REST service and it's response can be change according to status. For example; When I send a request and the response can be two types. The first one like that
{
"status": "success",
"user": {
"user_id": 3554,
"full_name": "test",
"email_address": "test#test1.com",
"end_date": null
}
}
The second type is like that
{
"status": "failure",
"reason": "email_taken"
}
The response according to "status" which comes with response. I searched this problem and find some solutions (custom converter, set custom converter etc.) But I think these are not clear enough . Are there any solution like that; if "status" is success, convert to json response to User model, else convert json response to FailureModel?
Retrofit dependency : implementation 'com.squareup.retrofit:retrofit:1.9.0'
If the only solution is custom converter, please explain it clearly because I am really new on this topic.

It is possible with custom json deserializer. You only have user when the status is success in case it is not you have the reason. In case you have status error and try to access user its null.
public class CustomConvertor implements JsonDeserializer<Response> {
#Override
public Response deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
Gson gson = new Gson();
Response response = gson.fromJson(json, Response.class);
if (response.getStatus().equals("success")) {
// The full response as a json object
final JsonObject jsonObject = json.getAsJsonObject();
// The user attribute in the JSON received
final JsonElement jsonElement = jsonObject.get("user");
User user = gson.fromJson(jsonElement, User.class);
response.setUser(user);
}else{
// you could do this
// not needed as json is deserialized to Response already
// just for the example
final JsonObject jsonObject = json.getAsJsonObject();
String reason = jsonObject.getAsJsonPrimitive("reason").getAsString();
response.setReason(reason);
}
return response;
}
}
The retrofit part
GsonBuilder gsonBuilder =new GsonBuilder();
gsonBuilder.registerTypeAdapter(Response.class, new CustomConvertor());
Gson gson = gsonBuilder.create();
GsonConverterFactory gsonConverterFactory = GsonConverterFactory.create(gson);
Retrofit retrofit = new Retrofit.Builder()
...// other setups
.addConverterFactory(gsonConverterFactory).build();
Then
// service is my case
Service service = retrofit.create(Service.class);
// call enqueue in your case.for testing i used mockwebserver
Response response = service.exampleJson().execute().body();
Log.i("User: ","" + response.geUser().getFullname());
in case of error
Log.i("Error: ","" + response.getReason());
You can get your pojos from http://www.jsonschema2pojo.org/
Pojo's
Response.java
public class Response {
#SerializedName("status")
#Expose
private String status;
#SerializedName("user")
#Expose
private User user;
#Expose
#SerializedName("reason")
private String reason;
public void setReason(String reason) {
this.reason = reason;
}
public String getReason() {
return reason;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
User.java
public class User {
#SerializedName("user_id")
#Expose
private int userId;
#SerializedName("full_name")
#Expose
private String fullName;
#SerializedName("email_address")
#Expose
private String emailAddress;
#SerializedName("end_date")
#Expose
private Object endDate;
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
public Object getEndDate() {
return endDate;
}
public void setEndDate(Object endDate) {
this.endDate = endDate;
}
}
The other way
Call<Response> auth = .// setup
auth.enqueue(new Callback<Response>() {
#Override
public void onResponse(Call<Response> call, Response<Response> response) {
if (response.isSuccessful() ) {
Response respojo = response.body();
if(respojo.getStatus().equals("success"){
Log.i("User: ","" + respojo.getUser().getFullname());
}else {
Log.i("Error: ","" + respojo.getReason());
}
}
} else {
response.errorBody();
}
}
#Override
public void onFailure(Call<Response> call, Throwable t) {
t.printStackTrace();
}
});

You can use a unique model and handle both cases with it :
public class UserResponseModel{
private String status;
private String reason;
private UserModel user;
// getter/setter
boolean isFailure(){
return status == "failure"
}
boolean isSuccess(){
return status == "success"
}
}
you may then do
UserResponseModel response
if( response.isSuccess() ) // do whatever with response.user
else // do whatever with response.reason

With your retrofit 2.0 best idea is to use Gson converter. Just add #Nullable annotation with your optional json key (in your case user and reason) so it does not crash while parsing or does not generate nullpointer exception. So your model class look like as follows.
public class YourModelClass {
#SerializedName("status")
#Expose
public String status;
#Nullable
#SerializedName("user")
#Expose
public User user;
#Nullable
#SerializedName("reason")
#Expose
public String reason;
public class User {
#SerializedName("user_id")
#Expose
public Integer userId;
#SerializedName("full_name")
#Expose
public String fullName;
#SerializedName("email_address")
#Expose
public String emailAddress;
#SerializedName("end_date")
#Expose
public Object endDate;
}
}
In your Activity or fragment where you are requesting parse it as follows
#Override
public void onResponse(Call<YourModelClass> call, Response<YourModelClass> response) {
if(response.body.yourModelClass.status.equals("succ")) {
User changesList = response.body().user;
//perform action with user data
} else {
Log.d("failer", response.body().reason)
}
}
#Override
public void onFailure(Call<YourModelClass> call, Throwable t) {
t.printStackTrace();
}
I hope its work for you.
Use android studio plugin DTO Genrater for creating pojo.

You can have an englobing class for this, for example:
public class Foo {
String status;
String reason;
UserModel user;
// Constructors, getter/setter, others
// ...
}
then call Retrofit like,
Call<Foo> callToYourAPI();
and when you want to have a user:
if (foo.reason == "success") // or if (foo.user != null)
// do something with foo.user
The conversion is done automatically in such a case. If your problem was having a field that can be of one type or another, you would have needed a converter.

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;

What is the correct way to consume and produce JSON data in Spring Boot from an Android Volley request

I'm unsure how to correctly send and receive requests from both the Android side and from the server side.
Lets say for example, during registration, I want to check if a user exists by checking their email address against the DB.
My current understanding of how to implement this would be as follows:
Android request code:
#Override
public void onClick(View v) { //Assume this request is performed on a button click
JSONObject registrationRequestDetails = new JSONObject(); //Creating a JSON object to be sent to the server
try {
registrationRequestDetails.put("email", emailBox.getText().toString());
} catch (JSONException e) {
Log.e("Couldn't create JSON: ", e.toString());
}
JsonObjectRequest loginRequest = new JsonObjectRequest(Request.Method.POST,
URL,
loginRequestDetails,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
if (response.get("result").equals("registered")) {
//Assuming a JSON object is returned here, something akin to "result":"registered" if the email does exist - do something
} else {
//Email doesn't exist
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Something: ", error.toString());
}
});
loginRequestQueue.add(loginRequest);
}
});
Spring Boot server code:
UserController.java
#RequestMapping(value = "/register", method = RequestMethod.POST, consumes = "application/json", produces = "application/json") //Want to accept JSON & return JSON
//I return a Map below because I do not understand if this is the correct way to return JSON format - what is the correct way??
public Map<String, String> registerNewUser(#RequestBody final Map<String, String> details) {
return registrationService.checkIfUserAlreadyExists(details);
}
RegistrationService.java
//Assume repo is injected that checks if email exists
public Map<String, String> checkIfUserAlreadyExists(Map<String, String> user) { //Should I be returning response status instead of JSON?
Map<String, String> resultMap = new HashMap<>();
if (usersRepository.existsByEmailAddress(user.get("email_address"))) {
resultMap.put("result", "error");
return resultMap;
} else {
//Save email if not registered
resultMap.put("result", "registered");
return resultMap;
}
}
Currently, this works. But i'm unsure if it is the correct way to go about this. Can anyone explain what is the correct way to accept and return JSON data?
Also, during the registration process for example, what should actually be returned upon successful (or not) registration from the server?
In programming there is no correct or wrong solution. However if you want to make your life easier handling json i recommend you using APIs for json serializtion e.g GSON.
this link is a tutorial on how to integrate and use Gson: https://medium.com/quick-code/parsing-json-on-android-using-gson-and-volley-83d6715776f8
this link is the github of the dependency:
https://github.com/google/gson
Also feel free to search other library for serialization.
UPDATE:
A good server side answer for a sign up would be a user with his auto generated ID or a boolean.
With the first solution -User with auto generated ID- a null answer means a failure a complet user means a success.
With the second well it's a boolean.
Forget about Volley, use Retrofit. Retrofit converts json response into Java objects automatically, using Volley you will need to do extra work for that. And I will explain rest-api part too. If you construct your structure like what i explain below, you will handle scaling and adding more endpoints to your app like a pro :)
----------------------------ANDROID-------------------------------
Retrofit
Add these dependencies to android
implementation 'com.squareup.okhttp:okhttp:2.7.2'
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
Now we need an interface that are going to mimic our rest-apis in android client
public interface APIUser {
#POST("/registr")
Call<GenericResponse<User>> register(#Body User user);
}
This is for registration. Here we have 2 classes, GenericResponse and User.
GenericResponse is generic type of class and we use it for both response data and error(if occurres). It is generic type because we want to use it for all our responses which can be of different types.
User is just simple java class holds user fields.
CustomError holds response message and code.
GenericResponse
public class GenericResponse<T> {
public CustomError error;
public T data;
}
User
public class User {
public String email;
}
CustomError
public class CustomError implements Serializable {
private Integer code;
private String message;
}
How to use it to post request
You write this registration code in where you want your code to be.
User user = new User();
user.setEmail(email);
OkHttpClient client = getOkHttpClient(context);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://yourDomainOrIpAddress/endpoint")
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
apiDicts = retrofit.create(APIDicts.class);
apiDicts.register()
.enqueue(new Callback<GenericResponse<User>>() {
#Override
public void onResponse(Call<GenericResponse<User>> call, retrofit2.Response<GenericResponse<User>> response) {
if(response.body().error==null){
// you can do someting with response.body().error.code and response.body().error.message. Or simple show them with toast
} else if(response.body().data!=null){
User user = response.body().data;
// you got your user object back after successfull registration
} else {
/// log something went really bad
}
}
#Override
public void onFailure(Call<GenericResponse<User>> call, Throwable t) {
//something is wrong with server/api
}
});
}
-------------------------------------------API-----------------------------------------
GenericResponse , CustomError and User is same class we use it in both android client and web service.
PS. GenericResponse is not generic here. Simple class.
public class GenericResponse {
private CustomError error;
private Object data;
}
RestController class
#PostMapping("/register")
public GenericResponse registerNewUser(#RequestBody User user) {
return registrationService.checkIfUserAlreadyExists(user);
}
In service class
public GenericResponse checkIfUserAlreadyExists(User user) {
GenericResponse genRes = new GenericResponse();
if (usersRepository.existsByEmailAddress(user.getEmail())) {
genRes.setError(new CustomError(1001, "User email already exists"))
return genRes;
} else {
user = dao.registerUser(user);
genRes.setUser(user);
return genRes;
}
}
Last words.
Despite of error message you are sending use custom error codes, such as 1001 for user not found, 1002 for already registered
To answer your question, I'll attempt to solve your problem by using my own personal experience with registering users. Your best bet is to use a serializer like Jackson (example below) or GSON. This will allow you to conveniently create Java POJO's from JSON data and create JSON from Java POJO's. Notice I am utilizing a Builder method, this is just another convenient way for you to build your models for unit tests, integration testing, or in general like below.
Also check out Spring Security techniques, so you can properly encode the user's password, etc. The following would be a good resource.
https://www.baeldung.com/spring-security-registration
UserController.java
#PostMapping(value="/register", produces = "application/json", consumes = "application/json")
public ResponseEntity<?> signUp(#RequestBody #Validated User user, BindingResult bindingResult, UriComponentsBuilder uri) {
if (bindingResult.hasErrors()) {
return BadRequest.of(bindingResult).asResponseEntity();
}
if (userService.userAlreadyExists(user.getUsername())) {
return BadRequest.ofAlreadyExists(USER_USERNAME, "User already exists. Please sign in with different username.").asResponseEntity();
}
user = User.builder()
.from(user)
.build();
return userService.save(user, uri);
}
User.java
#JsonDeserialize(builder = User.Builder.class)
#JsonSerialize
public class User {
#Id
private UUID id;
#NotNull
private String firstName;
#NotNull
private String lastName;
#NotNull
private String username;
#NotNull
private String password;
#NotNull
private Integer role;
#NotNull
#DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
private LocalDateTime createdDateTime;
#NotNull
#DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
private LocalDateTime lastModifiedDateTime;
public User(Builder builder ) {
this.id = builder.id;
this.firstName = builder.firstName;
this.lastName = builder.lastName;
this.username = builder.username;
this.password = builder.password;
this.role = builder.role;
this.createdDateTime = builder.createdDateTime;
this.lastModifiedDateTime = builder.lastModifiedDateTime;
}
public static Builder builder() {
return new Builder();
}
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonPOJOBuilder(withPrefix = "")
public static final class Builder {
private UUID id;
private String firstName;
private String lastName;
private String username;
private String password;
private Integer role;
private LocalDateTime createdDateTime;
private LocalDateTime lastModifiedDateTime;
public Builder from(User user) {
return this.id(user.id)
.firstName(user.firstName)
.lastName(user.lastName)
.username(user.username)
.password(user.password)
.role(user.role)
.createdDateTime(user.createdDateTime)
.lastModifiedDateTime(user.lastModifiedDateTime);
}
public Builder id(UUID id) {
this.id = id;
return this;
}
public Builder firstName(String firstName) {
this.firstName = firstName;
return this;
}
public Builder lastName(String lastName) {
this.lastName = lastName;
return this;
}
public Builder username(String username) {
this.username = username;
return this;
}
public Builder password(String password) {
this.password = password;
return this;
}
public Builder role(Integer role) {
this.role = role;
return this;
}
public Builder createdDateTime(LocalDateTime createdDateTime) {
this.createdDateTime = createdDateTime;
return this;
}
public Builder lastModifiedDateTime(LocalDateTime lastModifiedDateTime) {
this.lastModifiedDateTime = lastModifiedDateTime;
return this;
}
public Builder applyDefaults() {
if (this.id == null) {
this.id = UUID.randomUUID();
}
if (this.createdDateTime == null) {
createdDateTime = LocalDateTime.now();
}
if (this.lastModifiedDateTime == null) {
lastModifiedDateTime = LocalDateTime.now();
}
return this;
}
public User build() {
return new User(applyDefaults());
}
public UUID getId() {
return id;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public Integer getRole() {
return role;
}
public LocalDateTime getCreatedDateTime() {
return createdDateTime;
}
public LocalDateTime getLastModifiedDateTime() {
return lastModifiedDateTime;
}
}
public UUID getId() {
return id;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getRole() {
return role;
}
public LocalDateTime getCreatedDateTime() {
return createdDateTime;
}
public LocalDateTime getLastModifiedDateTime() {
return lastModifiedDateTime;
}
}

How to show a list in Android by using retrofit library?

I have to show A list in an Activity
MY API key is:
http://api.cuidadotechnologies.com/NSSPL/leave_dtls.php
Using GSON converter and retrofit library.
this API throws response in JSON like this
{
"status": 0,
"response_data": [
{
"id": "12",
"uid": "USER00000003",
"reason": "Test",
"type": "Plan Leave",
"SataDate": "2018-09-18",
"EndDate": "2018-09-25",
"ApprovedBy": "USER00000002",
"ApprovedDate": "2018-09-18",
"Status": "REJECTED",
"Remarks": "Test Reject"
},
{
"id": "13",
"uid": "USER00000003",
"reason": "Wedding",
"type": "Plan Leave",
"SataDate": "2018-01-28",
"EndDate": "2018-02-05",
"ApprovedBy": "USER00000002",
"ApprovedDate": "2018-09-18",
"Status": "APPROVED",
"Remarks": "Ok"
}
]
}
I am novice in this method please help me to do this step by step.
Try this way..
make retrofit object..
public class ApiClient {
private final static String BASE_URL = "http://api.cuidadotechnologies.com/NSSPL/";
public static ApiClient apiClient;
private Retrofit retrofit = null;
public static ApiClient getInstance() {
if (apiClient == null) {
apiClient = new ApiClient();
}
return apiClient;
}
//private static Retrofit storeRetrofit = null;
public Retrofit getClient() {
return getClient(null);
}
private Retrofit getClient(final Context context) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder client = new OkHttpClient.Builder();
client.readTimeout(60, TimeUnit.SECONDS);
client.writeTimeout(60, TimeUnit.SECONDS);
client.connectTimeout(60, TimeUnit.SECONDS);
client.addInterceptor(interceptor);
client.addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
return chain.proceed(request);
}
});
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client.build())
.addConverterFactory(GsonConverterFactory.create())
.build();
return retrofit;
}
}
make interface for api calling.
public interface ApiInterface {
#GET("leave_dtls.php")
Call<ResponseData> getData();
}
make pojo class for response.
public class ResponseDataItem{
#SerializedName("Status")
private String status;
#SerializedName("uid")
private String uid;
#SerializedName("reason")
private String reason;
#SerializedName("ApprovedDate")
private String approvedDate;
#SerializedName("Remarks")
private String remarks;
#SerializedName("ApprovedBy")
private String approvedBy;
#SerializedName("id")
private String id;
#SerializedName("type")
private String type;
#SerializedName("EndDate")
private String endDate;
#SerializedName("SataDate")
private String sataDate;
public void setStatus(String status){
this.status = status;
}
public String getStatus(){
return status;
}
public void setUid(String uid){
this.uid = uid;
}
public String getUid(){
return uid;
}
public void setReason(String reason){
this.reason = reason;
}
public String getReason(){
return reason;
}
public void setApprovedDate(String approvedDate){
this.approvedDate = approvedDate;
}
public String getApprovedDate(){
return approvedDate;
}
public void setRemarks(String remarks){
this.remarks = remarks;
}
public String getRemarks(){
return remarks;
}
public void setApprovedBy(String approvedBy){
this.approvedBy = approvedBy;
}
public String getApprovedBy(){
return approvedBy;
}
public void setId(String id){
this.id = id;
}
public String getId(){
return id;
}
public void setType(String type){
this.type = type;
}
public String getType(){
return type;
}
public void setEndDate(String endDate){
this.endDate = endDate;
}
public String getEndDate(){
return endDate;
}
public void setSataDate(String sataDate){
this.sataDate = sataDate;
}
public String getSataDate(){
return sataDate;
}
}
final response..
public class ResponseData {
#SerializedName("response_data")
private List<ResponseDataItem> responseData;
#SerializedName("status")
private int status;
public void setResponseData(List<ResponseDataItem> responseData){
this.responseData = responseData;
}
public List<ResponseDataItem> getResponseData(){
return responseData;
}
public void setStatus(int status){
this.status = status;
}
public int getStatus(){
return status;
}
}
called api into fragment or activity like this way..
ApiInterface apiInterface = ApiClient.getInstance().getClient().create(ApiInterface.class);
Call<ResponseData> responseDataCall=apiInterface.getData();
responseDataCall.enqueue(new Callback<ResponseData>() {
#Override
public void onResponse(Call<ResponseData> call, Response<ResponseData> response) {
if (response.isSuccessful() && response.body()!=null && response!=null){
List<ResponseDataItem> data=response.body().getResponseData();
}
}
#Override
public void onFailure(Call<ResponseData> call, Throwable t) {
t.printStackTrace();
}
});
You can use use POJO classes for converting JSON into classes. Use below website to convert JSON to POJO.
http://www.jsonschema2pojo.org
After that you can use Retrofit to call API and get response. Get reference from this site : https://square.github.io/retrofit/
After you convert into classes you can use Gson Methods for conversion.
SomeModelClass responseModel = new Gson().fromJson(response, SomeModelClass.class);
You can use this addConverterFactory(GsonConverterFactory.create()) retrofit method to directly convert response into class model if you don't want to do it manually.
And finally you can Create adapter using ViewHolder Pattern and use that adapter with RecyclerView.

how to get Json objects from json array and use them with model class

I want to link my received json data to my pojo class using gson library.I used volley library to receive the data.What should i do so that whenever i call getter methods from my pojo class then i get the received json data.
My Json data is in this format.
{
"vichList":[ {
id=1,
username="abc....},
{....},
]
}
I want to get this json data into my pojo class.
Vich.java
public class GetfeedResponse {
private List<Vich> vichList;
public List<Vich> getVichList() {
return vichList;
}
public void setVichList(List<Vich> vichList) {
this.vichList = vichList;
}
}
Vich.java
public class Vich {
private int id;
private String username;
private String full_name;
private String createdAt;
private int vich_id;
private String vich_content;
private String city;
private int like_count;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getFull_name() {
return full_name;
}
public void setFull_name(String full_name) {
this.full_name = full_name;
}
public String getCreatedAt() {
return createdAt;
}
public void setCreatedAt(String createdAt) {
this.createdAt = createdAt;
}
public int getVich_id() {
return vich_id;
}
public void setVich_id(int vich_id) {
this.vich_id = vich_id;
}
public String getVich_content() {
return vich_content;
}
public void setVich_content(String vich_content) {
this.vich_content = vich_content;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public int getLike_count() {
return like_count;
}
public void setLike_count(int like_count) {
this.like_count = like_count;
}
}
Here i am getting the json response using volley library.
httpUtil.getrequest(url,this,new VolleyCallback(){
#Override
public void onSuccess(String result){
GetfeedResponse getfeedResponse = new GetfeedResponse();
// for(Vich vich : getfeedResponse.getVichList()){
// }
Log.d("Response Result:",result);
}
How can i get objects from json array and use them with the help of pojo class?
Using Gson
Add the following dependency in your gradle:
implementation 'com.google.code.gson:gson:2.8.5'
In your onSuccess()
GetfeedResponse getfeedResponse=new Gson().fromJson(result, GetfeedResponse.class);
If you wish to use Volley and POJO its better to use custom GSON request. Check this link : Custom GSON request With Volley
GSON:
GetfeedResponse parsed = new Gson().fromJson(response, GetfeedResponse.class);
Jackson:
GetfeedResponse parsed = new ObjectMapper().readValue(response, GetfeedResponse.class);
Additionally, if you wanted to convert only list of Vich items (and you stripped your JSON accordingly) you could do following:
[ {
id=1,
username="abc....},
{....},
]
List<Vich> viches = Arrays.asList(new Gson().fromJson(vichItemsJson, Vich[].class));

Retrofit/Jackson error on deserializing

i'm trying to get a JSON from my web service and deserialize to my class UserSync, but i'm getting the following error:
Can not instantiate value of type [simple type, class com.example.breno.teste.model.User] from String value (''); no single-String constructor/factory method
at [Source: okhttp3.ResponseBody$BomAwareReader#fbf814f; line: 1, column: 86] (through reference chain: com.example.breno.teste.dto.UserSync["user"])
I've read some posts saying that i need to declare my User class static in UserSync, but when i do that, jackson can't find any user property, even with JsonDescription. Another posts say that i may need to declare a default constructor, so i did.
Here is the UserSync class:
#JsonIgnoreProperties(ignoreUnknown = true)
public class UserSync {
#JsonProperty("status")
private String Status;
#JsonProperty("currentDate")
private String CurrentDate;
#JsonProperty("message")
private String Message;
#JsonProperty("user")
private static User NewUser;
public UserSync() {
}
public String getStatus() {
return Status;
}
public String getCurrentDate() {
return CurrentDate;
}
public String getMessage() {
return Message;
}
public static User getNewUser() {
return NewUser;
}
The User class:
public class User implements Serializable {
#JsonProperty("userKey")
private UUID UserKey;
#JsonProperty("userPassword")
private String UserPassword;
#JsonProperty("userGroupKey")
private UUID UserGroupKey;
#JsonProperty("signInDate")
private String SignInDate;
#JsonProperty("active")
private boolean Active;
#JsonProperty("profilePicturePath")
private String ProfilePic;
#JsonProperty("completeName")
private String UserCompleteName;
#JsonProperty("email")
private String UserEmail;
#JsonProperty("isLogged")
private boolean IsLogged;
public User() {
}
public boolean getIsLogged() {
return IsLogged;
}
public void setIsLogged(boolean isLogged) {
IsLogged = isLogged;
}
public String getUserEmail() {
return UserEmail;
}
public void setUserEmail(String userEmail) {
UserEmail = userEmail;
}
public UUID getUserKey() {
return UserKey;
}
public void setUserKey(UUID userKey) {
UserKey = userKey;
}
public String getUserPassword() {
return UserPassword;
}
public void setUserPassword(String userPassword) {
UserPassword = userPassword;
}
public UUID getUserGroupKey() {
return UserGroupKey;
}
public void setUserGroupKey(UUID userGroupKey) {
UserGroupKey = userGroupKey;
}
public String getSignInDate() {
return SignInDate;
}
public void setSignInDate(String signInDate) {
SignInDate = signInDate;
}
public boolean getActive() {
return Active;
}
public void setActive(boolean active) {
Active = active;
}
public String getProfilePic() {
return ProfilePic;
}
public void setProfilePic(String profilePic) {
ProfilePic = profilePic;
}
public String getUserCompleteName() {
return UserCompleteName;
}
public void setUserCompleteName(String userCompleteName) {
UserCompleteName = userCompleteName;
}
}
My service class (Using now the postNewUser):
public interface UserService {
#GET("Login/LoginUser?")
Call<UserSync> login(#Query("email") String email, #Query("password") String password);
//region NewUser Services
#GET("Login/VerifyNewUser?")
Call<UserSync> validateNewUser(#Query("email") String email);
#POST("Login/PostNewUser")
Call<UserSync> postNewUser(#Body User user);
//endregion
}
And finally, the JSON:
{
"status": "OK",
"currentDate": "20/07/2017 11:59:02",
"message": "teste",
"user": {
"userKey": "8e2f0d2d-3522-472d-be1d-28791367f4ee",
"email": "teste_teste#hotmail.com",
"userPassword": "123456",
"profilePicturePath": "teste",
"completeName": "Jorge",
"userGroupKey": null,
"signInDate": "2017-07-07T16:26:06.097",
"active": true,
"isLogged": true
}
}
Can someone help me, please?
EDIT 1 - Here is the method that i'm using to do the retrofit call:
public void register(User user) {
Call<UserSync> postCall = new RetrofitInitializator().getUserService().postNewUser(user);
postCall.enqueue(getRegisterCallback());
}
#NonNull
private Callback<UserSync> getRegisterCallback() {
return new Callback<UserSync>() {
#Override
public void onResponse(Call<UserSync> call, Response<UserSync> response) {
User user = response.body().getNewUser();
}
#Override
public void onFailure(Call<UserSync> call, Throwable t) {
Log.e("Register - onFailure", t.getMessage());
}
};
}
EDIT 2 - The retrofitInicializator class:
public class RetrofitInitializator {
private final Retrofit retrofit;
public RetrofitInitializator() {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder builder = new OkHttpClient
.Builder();
builder.addInterceptor(interceptor);
retrofit = new Retrofit.Builder()
.baseUrl("http://192.168.15.6:7071/api/")
.addConverterFactory(JacksonConverterFactory.create())
.client(builder.build())
.build();
}
public UserService getUserService() {
return retrofit.create(UserService.class);
}
}
I managed to resolve my problem switching the type User to JsonNode and doing the convertion after this.
#JsonProperty("status")
private String Status;
#JsonProperty("currentDate")
private String CurrentDate;
#JsonProperty("message")
private String Message;
#JsonProperty("user")
private JsonNode NewUser;
and the convertion:
private User getUserFromUserAsync(UserSync userSync) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
return mapper.treeToValue(userSync.getNewUser(), User.class);
}

Categories

Resources