Retrofit + GSON parse an Array of objects - android

I receive this jason as a response from a WS:
[
[
"test0",
"test0"
],
[
"test1",
"test1"
],
[
"test2",
"test2"
],
[
"test3",
"test3"
],
[
"test4",
"test4"
],
[
"test5",
"test5"
]
]
Notice that there are no name-value fields the json is an array of strings arrays.
I tried several attemps to parse the response. I tried with a pojo with a List of strings but I have the same error always:
retrofit.RetrofitError: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $
MyPOJO for retrofit callback is the next one:
public class VotePollResults {
private List<PartialResult> fields;
public List<PartialResult> getFields() {
return fields;
}
public void setFields(List<PartialResult> fields) {
this.fields = fields;
}
public class PartialResult {
private String description;
private Integer votes;
public PartialResult(String description, Integer votes) {
this.description = description;
this.votes = votes;
}
public String getDescription() {
return description;
}
public Integer getVotes() {
return votes;
}
}
}
I have a List with a custom object, the one that handle that json structure.

Well I resolved the issue.
I have to use this as callback on retrofit
Callback<List<List<String>>>
Hope this helps to someone...

It looks like you are trying to parse Object instead of Array. In case of you response this code will work:
String[][] items = gson.fromJson(s, String[][].class);

Related

Parsing unsuccessfully JSON Objects with retrofit2

I am using retrofit2 in my code with gson.
i can parse almost all needed, but when parsing a specific JSON, I have a problem.
This is the JSON:
{
"data": [
{
"id": "001",
"direccion": "Cascada 3",
"provincia": "Burgos"
},
{
"id": "002",
"direccion": "Lago 21",
"provincia": "Zamora"
}
]
}
I know that what I am going to write has been commented a lot but, please, read until the end
When parsing it shows this error:
Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
If I delete the name of the object “data” from JSON, then I can parse it perfectly, like this:
[
{
"id": "001",
"direccion": "Cascada 3",
"provincia": "Burgos"
},
{
"id": "002",
"direccion": "Lago 21",
"provincia": "Zamora"
}
]
The JSON continues to open with an object, but it can be parsed perfectly.
This leads me to think that I am not indicating in the code how to parse the object called "data", I think the problem is that.
Tiendas.java (I use #serializedName for a possible solution that I have read but it does not work)
import com.google.gson.annotations.SerializedName;
public class Tiendas {
#SerializedName("id")
private int id;
#SerializedName("provincia")
private String provincia;
#SerializedName("direccion")
private String direccion;
public int getId() {
return id;
}
public String getProvincia() {
return provincia;
}
public String getDireccion() {
return direccion;
}
}
The interface
#GET("tiendas/tiends.json")
Call<List<Tiendas>> getTiendas();
MainActivity.java
private void getGETsinParametros() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://www.MY_URL_BASE.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
JsonPlaceHolderApi jspAPI = retrofit.create(JsonPlaceHolderApi.class);
Call<List<Tiendas>> call = jspAPI.getTiendas();
call.enqueue(new Callback<List<Tiendas>>() {
#Override
public void onResponse(Call<List<Tiendas>> call, Response<List<Tiendas>> response) {
if (!response.isSuccessful()) {
Log.e(TAG, "Código de respuesta no exítoso:" + response.code());
} else {
Log.d(TAG,"response code:"+response.code());
List<Tiendas> listaObtenida = response.body();
for(Tiendas stores: listaObtenida){
String content = "";
content += "id" + stores.getId() + "\n";
content += "provincia" + stores.getProvincia() + "\n";
content += "direccion" + stores.getDireccion() + "\n";
jsonText.append(content);
}
}
}
#Override
public void onFailure(Call<List<Tiendas>> call, Throwable t) {
Log.e("TAG, "error:" + t.getMessage());
}
});
}
Can someone tell me how to fix the error with "data", or with what is necessary to make it work?
The JSONs are external, so I can't modify them.
Thanks and regards.
You need to create the wrapper for the Array object to get the list of tiendas:
public class Data{
private List<Tiendas> data;
public List<Tiendas> getData() {
return data;
}
}
And call it in your interface:
#GET("tiendas/tiends.json")
Call<Data> getTiendas();
do not forget to use the new object at onResponse:
List<Tiendas> listaObtenida = response.body().getData();
The error has nothing to do with Retrofit. For a JSON, a field is an object, [] is an array, {} is a POJO.
In your first JSON, you have a data object with type List(or Array). Therefore, you will need to create a POJO on top (Access Modifier is omitted for simplicity)
class DataClazz {
List<Tiendas> data;
}

JSON object parsing using retrofit2.0

I'm trying to parse a JSON object using retrofit 2.0 following this guide, but it doesn't work. I think it's because of a difference in JSON format.
Here is a nested JSON object with the format:
{
"SearchService": {
"list_total_count": 531,
"RESULT": {
"CODE": "INFO-001",
"MESSAGE": "SUCCESS"
},
"row": [{
"ID": "1983",
"NAME": "SAN",
"NUM": "38",
}, {
"ID": "1984",
"NAME": "DU",
"NUM": "27",
}]
}
}
Here is class code using SerializedName:
RowList.java
public class RowList {
#SerializedName("row")
#Expose
private ArrayList<Row> rows= new ArrayList<>();
public ArrayList<Row> getRows() {
return rows;
}
public void setRows(ArrayList<Row> rows) {
this.rows= rows;
}
}
Row.java
public class Row{
#SerializedName("ID")
#Expose
private String id;
#SerializedName("NAME")
#Expose
private String name;
#SerializedName("NUM")
#Expose
private String num;
/*getter setter*/
}
Read that guide.
There are two approaches to create Model class. The first way is the manual approach, which requires you to learn how to use the Gson library. The second approach is you can also auto-generate the Java classes you need by capturing the JSON output and using jsonschema2pojo
Looks like you've attempted approach one, but haven't (yet?) tried reading over the Gson documentation.
Okay, you have a Row. That covers the objects within "row": [...], so you also need objects for the following:
"SearchService": {}
"RESULT": {}
I don't think the RowList class is necessary. List<Row> is fine.
For example,
class Result {
#SerializedName("CODE")
String code;
#SerializedName("MESSAGE")
String message;
}
class SearchService {
#SerializedName("list_total_count")
long count;
#SerializedName("RESULT")
Result result;
#SerializedName("row")
private ArrayList<Row> rows= new ArrayList<>();
}
(removed #Expose for conciseness)
Then, Retrofit would use Call<SearchService>

Retrofit Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path

Am trying Retrofit to get this response
POST : https://wrlyxhnjw3.execute-api.us-east-1.amazonaws.com/prod/pacakageinfo
BODY : {"type":"carwash"}
Response
[
{
"title": "SEDAN/NON SEDAN Exterior",
"choice": "Exterior Only",
"price": "$29.95/34.95 +",
"description": [
"Full body waterless car wash",
"Windows & Mirrors cleaning",
],
"addons": [
{
"price": "29.95",
"title": "Sedan 29.95$ USD"
},
{
"price": "34.95",
"title": "Non-Sedan SUV 34.95$ USD"
}
]
},
{
"title": "SEDAN/NON SEDAN",
"choice": "Exterior & Interior",
"price": "$34.95/44.95 +",
"description": [
"Full body waterless car wash",
"Leather cleaning & Care"
],
"addons": [
{
"price": "34.95",
"title": "Sedan 34.95$ USD"
},
{
"price": "44.95",
"title": "Non-Sedan/SUV 44.95$ USD"
}
]
}
]
PackagesAPI Class
public interface PackagesAPI {
#POST("/prod/pacakageinfo")
Call<List<PackagesAdapter.Item>> loadPackages(#Body PackagesFragment.PackageType packageType);
}
GetPackagecall (In a Package Fragment)
private void getPackagesCall(){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://wrlyxhnjw3.execute-api.us-east-1.amazonaws.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
PackagesAPI packagesAPI = retrofit.create(PackagesAPI.class);
Call<List<PackagesAdapter.Item>> call = packagesAPI.loadPackages(new PackageType("carwash"));
call.enqueue(this);
}
public class PackageType {
final String type;
PackageType(String type) {
this.type = type;
}
}
Public Objects in class PackageAdapter
public class Item {
String title;
String choice;
String price;
public List<String> description = new ArrayList<String>();
public List<Addon> addons = new ArrayList<Addon>();
}
public class Addon {
String price;
String title;
}
But it gives "Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path" exception?
I saw other posts like this and generally there's an issue with object definitions?
Am not able to figure out what's wrong here, I tried jsonschema2pojo.
You should try and make Item and Addon classes to be static or move them into their own class definitions (out of PackageAdapter). So in this solution, I am assuming that you move these classes to their separate class files/definitions if there are no compelling reasons for having them as inner classes.
In Item.java:
public class Item {
String title;
String choice;
String price;
public List<String> description = new ArrayList<String>();
public List<Addon> addons = new ArrayList<Addon>();
}
In Addon.java
public class Addon {
String price;
String title;
}
Instead of making the member variables to be public, please try moving either making these inner classes to be static, or move them to separate class files (recommended). Test it out and let us know if it solves the problem.

Gson throws "BEGIN_OBJECT expected but BEGIN_ARRAY found" - how to use TypeToken

Trying out Gson for the first time instead of looping through the JSON objects for speed.
This is my input data set for parsing
{
"data": [
{
"access_token": "XXXXX",
"category": "Community",
"name": "Startup notes by Vrashabh",
"id": "XXXXX",
"perms": [
"ADMINISTER",
"EDIT_PROFILE",
"CREATE_CONTENT",
"MODERATE_CONTENT",
"CREATE_ADS",
"BASIC_ADMIN"
]
},
{
"access_token": "XXXX",
"category": "Community",
"name": "Clean Bangalore",
"id": "XXXXX",
"perms": [
"ADMINISTER",
"EDIT_PROFILE",
"CREATE_CONTENT",
"MODERATE_CONTENT",
"CREATE_ADS",
"BASIC_ADMIN"
]
},
{
"access_token": "XXXXX",
"category": "Internet/software",
"name": "Getmeetin",
"id": "XXXXX",
"perms": [
"ADMINISTER",
"EDIT_PROFILE",
"CREATE_CONTENT",
"MODERATE_CONTENT",
"CREATE_ADS",
"BASIC_ADMIN"
]
}
],
"paging": {
"cursors": {
"before": "MTU3MzE3MTA0MjkyMjY4MQ==",
"after": "MjcyMTIwMzE2Mjk3NzI5"
}
}
}
And this is my gson mapping class
public class AccountsResponse {
ArrayList<AcResponseData> data;
ArrayList<PagingData> paging;
public class AcResponseData {
public String access_token;
public String category;
public String name;
public String id;
public String[] perms;
}
public class PagingData{
public Cursors cursors;
}
public class Cursors{
public String before;
public String after;
}
}
Code for parsing the data
AccountsResponse responseAccounts = gsonResponse.fromJson(response.getRawResponse(), AccountsResponse.class);
I Know I am supposed to not expect magic in terms of data conversion, I found the other questions on SO that ask me to implement TypeToken but I couldn't get it working for this case. How do I use TypeToken to get this data into the ORM
I wouldn't mind not reading that paging data also actually, if that needs to be eliminated from the ORM
UPDATE
Changed the ORM as below but now I get
java.lang.StackOverflowError
The problem is in your AccountsResponse class. It should be an object PagingData not an ArrayList, because from the json response in your question, "paging" is a JSON object not a JSON array. So, you should declare paging as a PagingData object not as an ArrayList of PagingData objects. That should fix it.
public class AccountsResponse {
ArrayList<AcResponseData> data;
PagingData paging;
public class AcResponseData {
public String access_token;
public String category;
public String name;
public String id;
public String[] perms;
}
public class PagingData{
public Cursors cursors;
}
public class Cursors{
public String before;
public String after;
}
}
Let me know if this helps.

Parsing complex JsonArray with GSON

Hi I already used GSON for parsing simple jsonobjects. But this time my response data is much complex. So I am struggling to parse that data.My data looks like :
[{"creator":"1", "users":[{"userName":"nilesh", "userAge":"25"},{"userName":"Me", "userAge":"25"}]},
{"creator":"2", "users":[{"userName":"nilesh", "userAge":"25"},{"userName":"Me", "userAge":"25"}]}
]
So I wrote one parsing class in following ways
public class UserData
{
#SerializedName("creator")
public String creator;
public List<Users> users;
public static class Users
{
#SerializedName("userName")
public String userName;
#SerializedName("userAge")
public String userAge;
}
}
But this is not working. Am I doing some thing wrong need some help regarding this parsing. thank you.
I tried to parse like this :
Gson gson = new Gson();
UserData users = gson.fromJson(result, UserData.class);
And it gives me error like this :
01-04 12:36:04.337: E/AndroidRuntime(15651): Caused by: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2
It is because your JSON you posted is invalid.
It should be like this The posted json below is your json which is valid.
[
{
"creator": "1",
"users": [
{
"userName": "nilesh",
"userAge": "25"
},
{
"userName": "Me",
"userAge": "25"
}
]
},
{
"creator": "2",
"users": [
{
"userName": "nilesh",
"userAge": "25"
},
{
"userName": "Me",
"userAge": "25"
}
]
}
]
The json you have posted contains errors at following points
users [ should be "users" :[
userAge : should be "userAge":
This is what I was looking for
public class UserData
{
public String creator;
public List<Users> user;
public class Users
{
public String userName;
public String userAge;
}
}
and I parse in following manner
Gson gson = new Gson();
Type type = new TypeToken<List<UserData>>(){}.getType();
List<UserData > objList = gson.fromJson(result, type);

Categories

Resources