Gson deserialization Expected BEGIN_ARRAY but was STRING [duplicate] - java

This question already has answers here:
Why does Gson fromJson throw a JsonSyntaxException: Expected BEGIN_OBJECT but was BEGIN_ARRAY?
(2 answers)
Closed 4 years ago.
I get the following json response from my api in my android application, i am using Gson deserialization to parse my data and populate my listview.
API Response:
{
"message":"success",
"success":"1",
"sessionKey":"a422e60213322845b85ae122de53269f",
"data":"[{\"system_id\":1,\"logo_url\":\"https:\\\/\\\/www.beta.system.com\\\/api\\\/icons\\\/3244ffjg.jpg\",\"organization_name\":\"Test Organasation\"}]"
}
My Class:
public class SystemResponse {
#Expose
#SerializedName("message")
private String message;
#Expose
#SerializedName("success")
private String statusCode;
#Expose
#SerializedName("sessionKey")
private String sessionKey;
#Expose
#SerializedName("data")
private List<System> data;
public String getStatusCode() {
return statusCode;
}
public void setStatusCode(String statusCode) {
this.statusCode = statusCode;
}
public String getSessionKey() {
return sessionKey;
}
public void setSessionKey(String sessionKey) {
this.sessionKey = sessionKey;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public List<System> getSystems() {
return data;
}
public void setSystems(List<System> data) {
this.data = data;
}
public static class System{
#Expose
#SerializedName("system_id")
private Long systemId;
#Expose
#SerializedName("logo_url")
private String logoUrl;
#Expose
#SerializedName("organization_name")
private String organizationName;
public Long getSystemId() {
return systemId;
}
public void setSystemId(Long systemId) {
this.systemId = systemId;
}
public String getLogoUrl() {
return logoUrl;
}
public void setLogoUrl(String logoUrl) {
this.logoUrl = logoUrl;
}
public String getOrganizationName() {
return organizationName;
}
public void setOrganizationName(String organizationName) {
this.organizationName = organizationName;
}
}
}
Api Request service, omitted the other code:
public Observable<SystemResponse> doServerAccountRequestApiCall(String param) {
return Rx2AndroidNetworking.get(ApiEndPoint.ENDPOINT_GET_ACCOUNTS)
.build()
.getObjectObservable(SystemResponse.class);
}
Request api call in my controller class, omitted the other code.
getCompositeDisposable().add(getDataManager() .doServerAccountRequestApiCall(params))
.subscribeOn(getSchedulerProvider().io())
.observeOn(getSchedulerProvider().ui())
.subscribe(new Consumer<SystemResponse>() {
#Override
public void accept(#NonNull SystemResponse response)
throws Exception {
//error here
}
}, new Consumer<Throwable>() {}));
I am getting getting this error:
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 92 path $.data

data parameter value is starting with " So it is a String not an array.
Use http://www.jsonschema2pojo.org/ to generate a model class.
Try this model class :
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Example {
#SerializedName("message")
#Expose
private String message;
#SerializedName("success")
#Expose
private String success;
#SerializedName("sessionKey")
#Expose
private String sessionKey;
#SerializedName("data")
#Expose
private String data;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getSuccess() {
return success;
}
public void setSuccess(String success) {
this.success = success;
}
public String getSessionKey() {
return sessionKey;
}
public void setSessionKey(String sessionKey) {
this.sessionKey = sessionKey;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}

Related

Android Java expected begin_object but was begin_array

Please Help me
This is my Models
Cases class
public class Cases {
#SerializedName("new")////this key value from json
#Expose
private String _new;
#SerializedName("active")
#Expose
private Integer active;
#SerializedName("critical")
#Expose
private Integer critical;
#SerializedName("recovered")
#Expose
private Integer recovered;
#SerializedName("1M_pop")
#Expose
private String _1MPop;
#SerializedName("total")
#Expose
private Integer total;
public String getNew() {
return _new;
}
public void setNew(String _new) {
this._new = _new;
}
public Integer getActive() {
return active;
}
public void setActive(Integer active) {
this.active = active;
}
public Integer getCritical() {
return critical;
}
public void setCritical(Integer critical) {
this.critical = critical;
}
public Integer getRecovered() {
return recovered;
}
public void setRecovered(Integer recovered) {
this.recovered = recovered;
}
public String get1MPop() {
return _1MPop;
}
public void set1MPop(String _1MPop) {
this._1MPop = _1MPop;
}
public Integer getTotal() {
return total;
}
public void setTotal(Integer total) {
this.total = total;
}
}
Deaths class
public class Deaths {
#SerializedName("new")
#Expose
private String _new;
#SerializedName("1M_pop")
#Expose
private String _1MPop;
#SerializedName("total")
#Expose
private Integer total;
public String getNew() {
return _new;
}
public void setNew(String _new) {
this._new = _new;
}
public String get1MPop() {
return _1MPop;
}
public void set1MPop(String _1MPop) {
this._1MPop = _1MPop;
}
public Integer getTotal() {
return total;
}
public void setTotal(Integer total) {
this.total = total;
}
}
public class Errors {//this is empty class
}
public class Parameters {//this is empty class
}
Tests class
public class Tests {
#SerializedName("1M_pop")
#Expose
private String _1MPop;
#SerializedName("total")
#Expose
private Integer total;
public String get1MPop() {
return _1MPop;
}
public void set1MPop(String _1MPop) {
this._1MPop = _1MPop;
}
public Integer getTotal() {
return total;
}
public void setTotal(Integer total) {
this.total = total;
}
}
Response class
public class Response {
#SerializedName("continent")
#Expose
private String continent;
#SerializedName("country")
#Expose
private String country;
#SerializedName("population")
#Expose
private Integer population;
#SerializedName("cases")
#Expose
private Cases cases;
#SerializedName("deaths")
#Expose
private Deaths deaths;
#SerializedName("tests")
#Expose
private Tests tests;
#SerializedName("day")
#Expose
private String day;
#SerializedName("time")
#Expose
private String time;
public String getContinent() {
return continent;
}
public String getCountry() {
return country;
}
public Integer getPopulation() {
return population;
}
public Cases getCases() {
return cases;
}
public Deaths getDeaths() {
return deaths;
}
public Tests getTests() {
return tests;
}
public String getDay() {
return day;
}
public String getTime() {
return time;
}
}
Covid19Model class
public class Covid19Model {
#SerializedName("get")
#Expose
private String get;
#SerializedName("parameters")
#Expose
private Parameters parameters;
#SerializedName("errors")
#Expose
private Errors errors;
#SerializedName("results")
#Expose
private Integer results;
#SerializedName("response")
#Expose
private List<Response> response;
public String getGet() {
return get;
}
public void setGet(String get) {
this.get = get;
}
public Parameters getParameters() {
return parameters;
}
public void setParameters(Parameters parameters) {
this.parameters = parameters;
}
public Errors getErrors() {
return errors;
}
public void setErrors(Errors errors) {
this.errors = errors;
}
public Integer getResults() {
return results;
}
public void setResults(Integer results) {
this.results = results;
}
public List<Response> getResponse() {
return response;
}
public void setResponse(List<Response> response) {
this.response = response;
}
Covid19WebAPI interface
public interface Covid19WebApi {
#Headers({
"x-rapidapi-host:covid-193.p.rapidapi.com",
"x-rapidapi-key:fb818f40c4msh9ed8e59abf0e867p11b3bfjsn0900d33b78ef"//this is my rapidapi key
})
#GET("statistics")
Call<Covid19Model> getData();
}
MainActivity class
public class MainActivity extends AppCompatActivity {//This is my app MainActivity
List<Response> responses;
private static final String BASE_URL = "https://covid-193.p.rapidapi.com/";//this is covid api website
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create());//this is convert json
Retrofit retrofit = builder.build();
Covid19WebApi covid19WebApi = retrofit.create(Covid19WebApi.class);
Call<Covid19Model> call = covid19WebApi.getData();//this is call api interfacee method
call.enqueue(new Callback<Covid19Model>() {
#Override
public void onResponse(Call<Covid19Model> call, Response<Covid19Model> response) {
responses = response.body().getResponse();
for (Object data:responses){
System.out.println(data);//This my error (expected begin_array but was begin_object )
}
}
#Override
public void onFailure(Call<Covid19Model> call, Throwable t) {
Toast.makeText(MainActivity.this,t.getLocalizedMessage().toString(),Toast.LENGTH_LONG).show();//this is toast message failure
}
});
}
}
What is the problem
My error code ("expected begin_array but was begin_object")
I can't find out what the problem is in these codes and the data doesn't come in response and gives an error instead
As you can see in JSON response, errors and parameters are comes as List.
So please change fields to list in Covid19Model
#SerializedName("parameters")
#Expose
private List<Parameters> parameters;
#SerializedName("errors")
#Expose
private List<Errors> errors;

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 to deserialize nested objects in java using object mapper

I have a sqs queue , I am polling for messages .
I get the message in following format
{
"Type" : "type_value",
"MessageId" : "message_id",
"TopicArn" : "topic_arn",
"Message" : "{\n \"contentType\": \"content_type_value\",\n \"content\": \"content_value\",\n \"eventName\": \"event_name\",\n \"eventTS\": 1591235390353\n}",
"Timestamp" : "2020-06-04T01:49:50.358Z",
"SignatureVersion" : "1",
"UnsubscribeURL" : "url"
}
when I get this body from SQS using code
String message = sqs_message_object.getBody()
Now I create a wrapper class for thie message body as following
public class SQSMessage
{
#JsonProperty("Type")
private String type;
#JsonProperty("MessageId")
private String messageId;
#JsonProperty("TopicArn")
private String topicArn;
#JsonProperty("Message")
private Message message;
#JsonProperty("Timestamp")
private String timestamp;
#JsonProperty("SignatureVersion")
private int signatureVersion;
#JsonProperty("UnsubscribeURL")
private String unSubscribeUrl;
public String getType()
{
return type;
}
public void setType(String type)
{
this.type = type;
}
public String getMessageId()
{
return messageId;
}
public void setMessageId(String messageId)
{
this.messageId = messageId;
}
public String getTopicArn()
{
return topicArn;
}
public void setTopicArn(String topicArn)
{
this.topicArn = topicArn;
}
public Message getMessage()
{
return message;
}
public void setMessage(Message message)
{
this.message = message;
}
public String getTimestamp()
{
return timestamp;
}
public void setTimestamp(String timestamp)
{
this.timestamp = timestamp;
}
public int getSignatureVersion()
{
return signatureVersion;
}
public void setSignatureVersion(int signatureVersion)
{
this.signatureVersion = signatureVersion;
}
public String getUnSubscribeUrl()
{
return unSubscribeUrl;
}
public void setUnSubscribeUrl(String unSubscribeUrl)
{
this.unSubscribeUrl = unSubscribeUrl;
}
}
And I deserialize the json string in to a SQSMessage object using Object Mapper
SQSMessage sqsMessage = null;
try
{
sqsMessage = objectMapper.readValue(message,SQSMessage.class);
}
catch(JsonProcessingException e2)
{
}
all the fields are getting mapped except for Message field .
because its not just a string but another class.
public class Message
{
private String contentType;
private Content content;
private String eventName;
private Date eventTS;
public String getContentType()
{
return contentType;
}
public void setContentType(String contentType)
{
this.contentType = contentType;
}
public Content getContent()
{
return content;
}
public void setContent(Content content)
{
this.content = content;
}
public String getEventName()
{
return eventName;
}
public void setEventName(String eventName)
{
this.eventName = eventName;
}
public Date getEventTS()
{
return eventTS;
}
public void setEventTS(Date eventTS)
{
this.eventTS = eventTS;
}
}
it fils to deserialize the field Message .
how do i Map the message field to Messaeg class as mentioned.
The error I get is
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `domain.Message`
(although at least one Creator exists): no String-argument constructor/factory method to deserialize
from String value ('{\n \"contentType\": \"content_type_value\",\n \"content\": \"content_value\",\n \"eventName\": \"event_name\",\n \"eventTS\": 1591235390353\n}')
at [Source: (String)"{

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;
}
}

I get org.springframework.http.converter.HttpMessageNotReadableException which get resolved after restarting server

The problem here is that the same request works fine after restarting the server.
This is the stackTrace error
Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Can not deserialize instance of java.lang.String out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token
This is the request Handler
#PostMapping("/buy-data")
#ApiOperation(value = "Guest buy data")
public ResponseEntity<?> buyData(#Valid #RequestBody BuyDataPaymentDto
paymentDto, Errors errors,#RequestParam(defaultValue = "web") String channel)
{
...
}
This is the BuyDataPaymentDto
public class BuyDataPaymentDto {
private long productId;
private String transactionId;
private String status;
private long paymentId;
private String cardLast4Digit;
private long networkId;
private String transactionRef;
#NotEmpty(message = "Receiver's msisdn cannot be blank")
private String receiverMsisdn;
public BuyDataPaymentDto() {
}
public long getProductId() {
return productId;
}
public void setProductId(long productId) {
this.productId = productId;
}
public String getTransactionId() {
return transactionId;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public long getPaymentId() {
return paymentId;
}
public void setPaymentId(long paymentId) {
this.paymentId = paymentId;
}
public String getCardLast4Digit() {
return cardLast4Digit;
}
public void setCardLast4Digit(String cardLast4Digit) {
this.cardLast4Digit = cardLast4Digit;
}
public long getNetworkId() {
return networkId;
}
public void setNetworkId(long networkId) {
this.networkId = networkId;
}
public String getTransactionRef() {
return transactionRef;
}
public void setTransactionRef(String transactionRef) {
this.transactionRef = transactionRef;
}
public String getReceiverMsisdn() {
return receiverMsisdn;
}
public void setReceiverMsisdn(String receiverMsisdn) {
this.receiverMsisdn = receiverMsisdn;
}
}

Categories

Resources