When trying to process JSON, I recive Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
This JSON is a client with array in data but i want to use the same data class for other for example employee, but I need that data can store different classes
{
"data": [
{
"client": "PAL",
"organization": "*",
"organization_info": {
"name": "*",
"searchKey": "0",
"id": "0"
},
"id": "*****",
"searchKey": "AJ23",
"commercialName": "MANOLO",
"fiscalName": "MANOLO",
"locations": [{
"address": "NUEVA",
"city": "SEVILLA",
"zipCode": "00000",
"country": "ES"}]
},
{
"client": "LAC",
"organization": "*",
"organization_info": {
"name": "*",
"searchKey": "0",
"id": "0"
},
"id": "*****",
"searchKey": "0ASD13",
"commercialName": "DANI",
"fiscalName": "DANI",
"locations": [{
"address": "FONTANA",
"city": "VALLADOLID",
"zipCode": "00000",
"country": "ES"
}]
}]
}
This JSON has a data object since it only has one result
{
"data": {
"client": "PAL",
"organization": "*",
"organization_info": {
"name": "*",
"searchKey": "0",
"id": "0"
},
"id": "*****",
"searchKey": "AJ2",
"commercialName": "MANOLO",
"fiscalName": "MANOLO",
"locations": [
"address": "NUEVA",
"city": "SEVILLA",
"zipCode": "00000",
"country": "ES"
}]
}
}
The idea of the Data class is that it be generic to be able to call different classes Customer, Provider, etc. from the main class.
public class Data<T> {
#SerializedName("data")
private final List<T> data;
String links;
public Data(List<T> data) {
super();
this.data = data;
}
public List<T> getData() {
return data;
}
//get and set method
public class Client {
private String client;
private String organization;
private Org_info organization_info;
private String id;
private String fiscalName;
private String searchKey;
private String commercialName;
private String phone;
private String email;
private ArrayList<Locations> locations;
public Cliente(Org_info organization_info, String client, String organization, String id, String fiscalName, String searchKey,String phone, String email,
String commercialName,ArrayList<Locations> locations) {
super();
this.organization_info=organization_info;
this.client = client;
this.organization = organization;
this.id = id;
this.fiscalName = fiscalName;
this.searchKey = searchKey;
this.commercialName = commercialName;
this.locations = locations;
}
//get and set method
How can I make the data class generic, and be able to store JSON data with the data node from both clients and providers, while receiving an array of data or a data object?
public static void main(String[] args){
conection();
InputStreamReader inputStreamReader = new InputStreamReader(http.getInputStream(), "UTF-8");
BufferedReader br = new BufferedReader(inputStreamReader);
StringBuilder sb = new StringBuilder();
int cp;
while ((cp = br.read()) != -1) {
sb.append((char) cp);
}
String output = sb.toString();
final Type tpEnvClient = new TypeToken<Data<Client>>(){}.getType();
final Data<Client> envEmp = new Gson().fromJson(output, tpEnvClient);
When trying to store an array I get an error because I can't store a list of clients.
{
"reservation_upto": {
"lng": 78.0098161,
"lat": 27.1752554,
"code": "AGC",
"name": "AGRA CANTT"
},
"debit": 3,
"doj": "28-05-2018",
"to_station": {
"lng": 78.0098161,
"lat": 27.1752554,
"code": "AGC",
"name": "AGRA CANTT"
},
"response_code": 200,
"boarding_point": {
"lng": 80.2755685,
"lat": 13.081674,
"code": "MAS",
"name": "CHENNAI CENTRAL"
},
"pnr": "4405474586",
"chart_prepared": false,
"journey_class": {
"code": "3A",
"name": null
},
THIS IS WHAT I HAVE TRIED USING VOLLEY
private void loaddata() {
String url = "https://api.railwayapi.com/v2/pnr-status/pnr/4655474586/apikey/q15rfl3kpz/";
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
progressDialog.dismiss();
JSONObject obj = null;
try {
String str="";
obj = response.getJSONObject("name");
str = String.valueOf(obj);
TextView tv = (TextView)findViewById(R.id.textView);
tv.append(str);
}
}
}
}
}
JSONObject obj = (JSONObject) object;
String doj = (String) obj.get("doj")
You can use JSONObject obj to find out the value of key doj.
Latter on, if you want to have the doj as any other datatype you can parse in that. May be this could help. I don't have much idea on Volley :)
Hi guys i have struck with one problem while i am trying to access one api services it is all working fine. But my issue iin processing the response .
I am using retrofit 2.0
Below is my json response for my api
{
"status": 200,
"success": "true",
"data": [
{
"works_node": [
{
"works_items": [
{
"work_id": "number",
"preference": "number",
"Task_created_time": "datetime yyyy-mm-dd h:m:s"
}
]
}
],
"questions_node": [
{
"questions_items": [
{
"q_id": "number",
"work_id": "number",
"question_text": "string",
"preference": "number"
}
]
}
],
"answers_node": [
{
"answers_items": [
{
"a_id": "number",
"q_id": "number",
"answer_text": "string",
"prefernce": "number",
"point": "number",
"is_suggest": "number",
"work_id": "number"
}
]
}
],
"answer_suggestions_node": [
{
"answer_suggestions_items": [
{
"a_id": "number",
"q_id": "number",
"answer_suggestion_text": "string",
"point": "number",
"work_id": "number"
}
]
}
]
}
]
}
Below is the api calling code
public void getWorkTaskConfig(){
ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
String DeviceImei=uf.getIMEI();
int userId=db.getUserId();
Call<WorkTaskConfig> call = apiService.getWorkTaskConfig
(new BasicData(new UserInfo(userId),new DeviceInfo(DeviceImei)));
call.enqueue(new Callback<WorkTaskConfig>() {
#Override
public void onResponse(Call<WorkTaskConfig> call, Response<WorkTaskConfig> response) {
try {
int apiStatus= response.body().getStatus();
Boolean apiSuccess=response.body().getSuccess();
if (apiStatus == Constants.RESULT_CODE_OK &&
apiSuccess.equals(Constants.RESULT_SUCCESS_OK)) { //data received successfully
List<Datum> apiAllWorkTaskConfigData=response.body().getData();
List<WorksNode> apiAllWorksNodeData=response.body().getData().getWorksNode(); // im facing
//the problem here ie i am not able to access the getWorksNode() function
//in Datum.java class.
}else{ //while retrieving data something went wrong.
}
} catch (Exception e) { e.printStackTrace(); }
}
#Override
public void onFailure(Call<WorkTaskConfig> call, Throwable t) { }
});
}
WorkTaskConfig.java
public class WorkTaskConfig {
#SerializedName("status")
#Expose
private Integer status;
#SerializedName("success")
#Expose
private Boolean success;
#SerializedName("data")
#Expose
private List<Datum> data = null;
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public Boolean getSuccess() {
return success;
}
public void setSuccess(Boolean success) {
this.success = success;
}
public List<Datum> getData() {
return data;
}
public void setData(List<Datum> data) {
this.data = data;
}
}
Datum.java
public class Datum {
#SerializedName("works_node")
#Expose
private List<WorksNode> worksNode = null;
public List<WorksNode> getWorksNode() {
return worksNode;
}
public void setWorksNode(List<WorksNode> worksNode) {
this.worksNode = worksNode;
}
}
Solution
Edit Json structure
Edit POJO class(Datum)
Edit Json Structure
data is an object, not array.
{
"status": 200,
"success": "true",
"data": {
"works_node": [{
"works_items": [{
"work_id": "number",
"preference": "number",
"Task_created_time": "datetime yyyy-mm-dd h:m:s"
}]
}],
"questions_node": [{
"questions_items": [{
"q_id": "number",
"work_id": "number",
"question_text": "string",
"preference": "number"
}]
}],
"answers_node": [{
"answers_items": [{
"a_id": "number",
"q_id": "number",
"answer_text": "string",
"prefernce": "number",
"point": "number",
"is_suggest": "number",
"work_id": "number"
}]
}],
"answer_suggestions_node": [{
"answer_suggestions_items": [{
"a_id": "number",
"q_id": "number",
"answer_suggestion_text": "string",
"point": "number",
"work_id": "number"
}]
}]
}
}
Edit POJO class
go to link below and generate the pojo class again.
http://www.jsonschema2pojo.org/
And Try this.
WorkTaskConfig taskConfig = reponse.body();
List<WorksNode> worksNode = taskConfig.getData().getWorksNode();
List<QuestionsNode> questionsNode = taskConfig.getData().getQuestionsNode();
List<AnswersNode> answersNode = taskConfig.getData().getAnswersNode();
List<AnswerSuggestionsNode> answerSuggestionsNode = taskConfig.getData().getAnswerSuggestionsNode();
Replace all WorkTaskConfig to JsonElement if you are facing some problem .
and Parse manually with Gson like..
String apiAllWorkTaskConfigData = response.body().getData();
WorkTaskConfig mWorkTaskConfig = new Gson.fromJson(apiAllworkTaskConfigData,WorkTaskConfig.class);
I have a response form server as :
[
{
"ID": "1",
"Title": "BIRATNAGAR",
"BankID": "1",
"BranchCode": "0",
"LocationID": "71500200",
"IsActive": "yes"
},
{
"ID": "2",
"Title": "BIRATNAGAR",
"BankID": "1",
"BranchCode": "0",
"LocationID": "71500900",
"IsActive": "yes"
},
{
"ID": "3",
"Title": "BIRATNAGAR",
"BankID": "1",
"BranchCode": "0",
"LocationID": "94361117",
"IsActive": "yes"
}
]
I have retrofit api as:
#POST("authapp/Restserver/api/Masterdata/getBranchListByBank")
Call> getBranchListByBank(#Query("api_key") String id);
I have called it as:
RetrofitArrayAPI service = retrofit.create(RetrofitArrayAPI.class);
Call<List<BankBranch>> call = service.getBranchListByBank(s);
call.enqueue(new Callback<List<BankBranch>>() {
#Override
public void onResponse(Call<List<BankBranch>> call, Response<List<BankBranch>> response) {
try {
List<BankBranch> banks = response.body();
for (int i = 0; i < banks.size(); i++) {
String id = banks.get(i).getTitle();
String name = banks.get(i).getID();
String marks = banks.get(i).getIsActive();
Log.i("ashihs", id + " " + marks + " " + name);
}
} catch (Exception e) {
Log.d("onResponse", "There is an error");
e.printStackTrace();
}
}
#Override
public void onFailure(Call<List<BankBranch>> call, Throwable t) {
Log.d("onFailure", t.toString());
}
});
But I cannot get the list of the bank branch. I get error as :
java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
Can any one help me?
Thanks in advance.
U probably got bad Api request it schould look like this:
api:
#POST("authapp/Restserver/api/Masterdata/getBranchListByBank")
Call<List<BankBranch>> getBranchListByBank(#Query("api_key") String id);
And the method schould look like this:
Call<List<BankBranch>> response = apiCall.getBranchListByBank(id);
response.enqueue(new Callback<List<BankBranch>>() {
#Override
public void onResponse(Call<List<BankBranch>> call, Response<List<BankBranch>> response) {
List<BankBranch> bankBranch = response.body();
}
#Override
public void onFailure(Call<List<BankBranch>> call, Throwable t) {
}
});
}
make sure Your model BankBranch fit the JSON response;
Retrofit makes things so easy for a noob like me. However, the API response structure that I'm requesting for my current project doesn't follow the same format as I have used before. I am unsure of whether I need to rewrite my POJO or make a custom deserializer in GSON. I cannot change the JSON structure and a custom deserializer seems daunting to me.
Here is the JSON:
{
"Green Shirt": [
{
"id": "740",
"name": “Nice Green Shirt",
"quantity": "0",
"make": "",
"model": "",
"price": “15.00",
"size": "XXS",
"sku": null,
"image": "https:\/\/google.com\/green_shirt.jpg",
"new_record": false,
"category_name": "",
"bar_code": "",
},
{
"id": "743",
"name": "Green Shirt",
"quantity": “68",
"make": "",
"model": "",
"price": “20.00",
"size": "XS",
"sku": null,
"image": "https:\/\/google.com\/green_shirt.jpg",
"new_record": false,
"category_name": "",
"bar_code": "",
}
],
"Dark Blue Jeans": [
{
"id": "1588",
"name": "Dark Blue Jeans",
"quantity": "0",
"make": "",
"model": "",
"price": "0.00",
"size": “S",
"sku": null,
"image": "https:\/\/google.com\/dark_blue_jeans.jpg",
"new_record": false,
"category_name": "",
"bar_code": "",
"category": null
},
{
"id": "1559",
"name": "Dark Blue Jeans",
"quantity": "4",
"make": "",
"model": "",
"price": "0.00",
"size": “XL",
"sku": null,
"image": "https:\/\/google.com\/dark_blue_jeans.jpg",
"new_record": false,
"category_name": "",
"bar_code": "",
"category": null
}
],
"White Belt": [
{
"id": "1536",
"name": "White Belt",
"quantity": "37",
"make": "",
"model": "",
"price": "0.00",
"size": "One Size",
"sku": null,
"image": "https:\/\/google.com\/white_belt.jpg",
"new_record": false,
"category_name": "",
"bar_code": "",
"category": null
}
]
}
Here is the POJO:
public class Product
{
private String model;
private String bar_code;
private String image;
private null sku;
private String new_record;
private String size;
private String id;
private null category;
private String price;
private String category_name;
private String name;
private String quantity;
private String make;
public String getModel ()
{
return model;
}
public void setModel (String model)
{
this.model = model;
}
public String getBar_code ()
{
return bar_code;
}
public void setBar_code (String bar_code)
{
this.bar_code = bar_code;
}
public String getImage ()
{
return image;
}
public void setImage (String image)
{
this.image = image;
}
public null getSku ()
{
return sku;
}
public void setSku (null sku)
{
this.sku = sku;
}
public String getNew_record ()
{
return new_record;
}
public void setNew_record (String new_record)
{
this.new_record = new_record;
}
public String getSize ()
{
return size;
}
public void setSize (String size)
{
this.size = size;
}
public String getId ()
{
return id;
}
public void setId (String id)
{
this.id = id;
}
public null getCategory ()
{
return category;
}
public void setCategory (null category)
{
this.category = category;
}
public String getPrice ()
{
return price;
}
public void setPrice (String price)
{
this.price = price;
}
public String getCategory_name ()
{
return category_name;
}
public void setCategory_name (String category_name)
{
this.category_name = category_name;
}
public String getName ()
{
return name;
}
public void setName (String name)
{
this.name = name;
}
public String getQuantity ()
{
return quantity;
}
public void setQuantity (String quantity)
{
this.quantity = quantity;
}
public String getMake ()
{
return make;
}
public void setMake (String make)
{
this.make = make;
}
#Override
public String toString()
{
return "ClassPojo [model = "+model+", bar_code = "+bar_code+", image = "+image+", sku = "+sku+", new_record = "+new_record+", size = "+size+", id = "+id+", category = "+category+", price = "+price+", category_name = "+category_name+", name = "+name+", quantity = "+quantity+", make = "+make+"]";
}
}
Here is the request and Retrofit interface:
public static void requestData(String username,String password) {
RestAdapter.Builder builder = new RestAdapter.Builder()
.setClient(new OkClient(new OkHttpClient()))
.setEndpoint(ENDPOINT);
if (username != null && password != null) {
// concatenate username and password with colon for authentication
final String credentials = username + ":" + password;
builder.setRequestInterceptor(new RequestInterceptor() {
#Override
public void intercept(RequestFacade request) {
// create Base64 encodet string
String string = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
request.addHeader("Accept", "application/json");
request.addHeader("Authorization", string);
}
});
}
RestAdapter adapter = builder.build();
ProductAPI api = adapter.create(ProductAPI.class);
api.getInventory(new Callback<List<Product>>() {
#Override
public void success(List<Product> products, Response response) {
Log.d(TAG, response.getUrl());
Log.d(TAG, response.getReason());
mInventory = product;
}
#Override
public void failure(RetrofitError error) {
Log.d(TAG,error.getMessage());
}
});
}
public interface ProductAPI {
#GET("/v2/get-inventory")
public void getInventory(Callback<List<Product>> response);
}
This is the error I get because the JSON starts with '{' instead of '['
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
Your JSON is invalid, try formatting it properly first before doing anything else.
Properly formatted:
{
"Green Shirt": [
{
"id": "740",
"name": "Nice Green Shirt",
"quantity": "0",
"make": "",
"model": "",
"price": "15.00",
"size": "XXS",
"sku": null,
"image": "https:\\/\\/google.com\\/green_shirt.jpg",
"new_record": false,
"category_name": "",
"bar_code": ""
},
{
"id": "743",
"name": "Green Shirt",
"quantity": "68",
"make": "",
"model": "",
"price": "20.00",
"size": "XS",
"sku": null,
"image": "https:\\/\\/google.com\\/green_shirt.jpg",
"new_record": false,
"category_name": "",
"bar_code": ""
}
],
"Dark Blue Jeans": [
{
"id": "1588",
"name": "Dark Blue Jeans",
"quantity": "0",
"make": "",
"model": "",
"price": "0.00",
"size": "S",
"sku": null,
"image": "https:\\/\\/google.com\\/dark_blue_jeans.jpg",
"new_record": false,
"category_name": "",
"bar_code": "",
"category": null
},
{
"id": "1559",
"name": "Dark Blue Jeans",
"quantity": "4",
"make": "",
"model": "",
"price": "0.00",
"size": "XL",
"sku": null,
"image": "https:\\/\\/google.com\\/dark_blue_jeans.jpg",
"new_record": false,
"category_name": "",
"bar_code": "",
"category": null
}
],
"White Belt": [
{
"id": "1536",
"name": "White Belt",
"quantity": "37",
"make": "",
"model": "",
"price": "0.00",
"size": "One Size",
"sku": null,
"image": "https:\\/\\/google.com\\/white_belt.jpg",
"new_record": false,
"category_name": "",
"bar_code": "",
"category": null
}
]
}
Some of the errors it had:
Error:Strings should be wrapped in double quotes.[Code 17, Structure 12]
Error:Strings should be wrapped in double quotes.[Code 17, Structure 28]
Error:Invalid comma, expecting }.[Code 141, Structure 53]
Error:Expecting string, not }.[Code 8, Structure 54]
Error:Strings should be wrapped in double quotes.[Code 17, Structure 67]
Error:Strings should be wrapped in double quotes.[Code 17, Structure 79]
Error:Invalid comma, expecting }.[Code 141, Structure 104]
Error:Expecting string, not }.[Code 8, Structure 105]
Error:Strings should be wrapped in double quotes.[Code 17, Structure 138]
Error:Strings should be wrapped in double quotes.[Code 17, Structure 192]
The problem seems exactly what it says. The response is an object that has an array and not an array directly:
{ [{},{},{}] }
If the response was:
[{},{},{}]
It would work, but as you cannot change the response format you should change your java. Instead of expecting a List of Products you should have an object that has a List of Products inside. That is how retrofit will map it.
Edit:
The response is actually as follows:
{[],[],[]}
Is not a list, is an object composed with three Lists of Objects Product
The mapping to an object will have to be:
public class Wrapper
{
List<Product> WhiteBelt;
List<Product> DarkBlueJeans;
List<Product> GreenShirt;
}
Something like that would be your structure. I dont believe is right, because you usally want a list and not an object with three lists inside "hardcoded".
Let me know if it helps
Edited:
So you need somthing like this:
{
"products":
[{ "name" : "Green Shirt"
"items":
[{"id": "740",
"name": “Nice Green Shirt",
"quantity": "0",
"make": "",
"model": "",
"price": “15.00",
"size": "XXS",
"sku": null,
"image": "https:\/\/google.com\/green_shirt.jpg",
"new_record": false,
"category_name": "",
"bar_code": ""
}]
}]
}
That would be a structure that accepts a list of Products and inside each prodcut you have the list of items (the one you already have).
In Java:
public class ProductList
{
List <ProductList> productList;
}
public class ProductList
{
String name;
List<Product> items;
}
Using your original Product class
I told Retrofit (GSON?) to look for a Map<String,List<Product>> instead of just a List<Product> and it figured it out, how convenient.
:
api.getInventory(new Callback<Map<String,List<Product>>>() {
#Override
public void success(Map<String,List<Product>> products, Response response) {
mInventory = products;
}
#Override
public void failure(RetrofitError error) {
Log.d(TAG,error.getMessage());
}
});
public interface ProductAPI {
#GET("/v2/get-inventory")
public void getInventory(Callback<Map<String,List<Product>>> response);
}