Custom deserializer or different class design Retrofit - java

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

Related

"Expected BEGIN_OBJECT but was STRING" error despite JSON being valid

I'm currently working on an end of the semester project. It is an android app that would function as both a music database and shop, and I am using the MusicBrainz API to fetch the information on releases and artists.
Unfortunately, I'm stuck on a very vital part of my project: the API itself. I keep getting this error
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $
Looking around online, I discovered that this was because the JSON itself was badly written, however, looking again and using a JSON validator made me realise that this was not the case. Here is the json I'm trying to fetch
{
"ipis": [],
"type": "Group",
"life-span": {
"end": "2017-02-04",
"begin": "1969",
"ended": true
},
"area": {
"name": "United Kingdom",
"id": "8a754a16-0027-3a29-b6d7-2b40ea0481ed",
"type": null,
"disambiguation": "",
"iso-3166-1-codes": ["GB"],
"type-id": null,
"sort-name": "United Kingdom"
},
"disambiguation": "",
"type-id": "e431f5f6-b5d2-343d-8b36-72607fffb74b",
"isnis": ["0000000123694269"],
"name": "Black Sabbath",
"begin_area": {
"name": "Birmingham",
"type": null,
"id": "226c4dca-ef2a-4d4b-ba25-4118d116557a",
"disambiguation": "",
"type-id": null,
"sort-name": "Birmingham",
"iso-3166-2-codes": ["GB-BIR"]
},
"id": "5182c1d9-c7d2-4dad-afa0-ccfeada921a8",
"gender-id": null,
"end-area": {
"name": "Birmingham",
"id": "226c4dca-ef2a-4d4b-ba25-4118d116557a",
"type": null,
"disambiguation": "",
"type-id": null,
"iso-3166-2-codes": ["GB-BIR"],
"sort-name": "Birmingham"
},
"begin-area": {
"name": "Birmingham",
"type": null,
"id": "226c4dca-ef2a-4d4b-ba25-4118d116557a",
"disambiguation": "",
"type-id": null,
"sort-name": "Birmingham",
"iso-3166-2-codes": ["GB-BIR"]
},
"country": "GB",
"sort-name": "Black Sabbath",
"gender": null,
"end_area": {
"name": "Birmingham",
"id": "226c4dca-ef2a-4d4b-ba25-4118d116557a",
"type": null,
"disambiguation": "",
"type-id": null,
"iso-3166-2-codes": ["GB-BIR"],
"sort-name": "Birmingham"
}
}
and here is part of my code:
My main method:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "Mainactivity";
JSONPlaceHolderArtist artistJSON;
Button b;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
artistJSON = MusicBrainzAPI.getClient().create(JSONPlaceHolderArtist.class);
b = findViewById(R.id.button);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getArtist();
}
});
}
private void getArtist() {
Call<ArtistAPI> call = artistJSON.getArtist("5182c1d9-c7d2-4dad-afa0-ccfeada921a8");
call.enqueue(new Callback<ArtistAPI>() {
#Override
public void onResponse(Call<ArtistAPI> call, Response<ArtistAPI> response) {
Log.e(TAG,"on response: " + response.body());
}
#Override
public void onFailure(Call<ArtistAPI> call, Throwable t) {
Log.i(TAG, "on failure: " + t.getLocalizedMessage());
}
});
}
}
The ArtistAPI class:
public class ArtistAPI {
String id, name, country, begin, end;
Boolean ended;
public String getArtistID() {
return id;
}
public String getArtistName() {
[...]
The Retrofit interface:
public interface JSONPlaceHolderArtist {
#GET("/artist/{id}/name?fmt=json")
Call<ArtistAPI> getArtist(#Path("id") String id);
}
and the API:
public class MusicBrainzAPI {
private static final String BASE_URL = "https://musicbrainz.org/ws/2/";
private static Retrofit retrofit = null;
public static Retrofit getClient() {
if (retrofit == null) {
Gson gson = new GsonBuilder().setLenient().create();
retrofit = new Retrofit.Builder().baseUrl(BASE_URL).
addConverterFactory(GsonConverterFactory.create(gson)).build();
}
return retrofit;
}
}
Any help? Thanks in advance!

How can I set label names manually on a loop springboot?

I have a JSON array below, I want to be able to set label names that make sense instead of the entity names. Am generating tables dynamically using this data, I want the rows to have names that make more sense to the end user by assigning custom Label names. the recordtype generates new tab names
This is my JSON
[
{
"country": "USA",
"projectId": "USAID2020,
"case": "2014",
"recordType": "Identification",
"itemDetails": [
{
"ItemValue": "023",
"Label": "hA",
"ItemValueLabel": "023",
"Name": "hA"
},
{
"ItemValue": "0005",
"Label": "hUM",
"ItemValueLabel": "0005",
"Name": "hUM"
},
{
"ItemValue": "5",
"Label": "hCounty",
"ItemValueLabel": "5",
"Name": "hCounty"
}
]
},
{
"country": "USA",
"projectId": "USAID2020",
"case": "2014",
"recordType": "Eligibility",
"itemDetails": [
{
"ItemValue": "023",
"Label": "hA",
"ItemValueLabel": "023",
"Name": "hA"
},
{
"ItemValue": "0005",
"Label": "hUM",
"ItemValueLabel": "0005",
"Name": "hUM"
},
{
"ItemValue": "0005",
"Label": "hPUM",
"ItemValueLabel": "0005",
"Name": "hPUM"
}
]
}
]
This is how I want the labels to appear
[
{
"country": "USA",
"projectId": "USAID2020,
"case": "2014",
"recordType": "Identification",
"itemDetails": [
{
"ItemValue": "023",
"Label": "Area Code",
"ItemValueLabel": "023",
"Name": "hA"
},
{
"ItemValue": "0005",
"Label": "Manager Identification",
"ItemValueLabel": "0005",
"Name": "hUM"
},
{
"ItemValue": "5",
"Label": "County Name",
"ItemValueLabel": "5",
"Name": "hCounty"
}
]
},
{
"country": "USA",
"projectId": "USAID2020",
"case": "2014",
"recordType": "Eligibility",
"itemDetails": [
{
"ItemValue": "023",
"Label": "Area Code",
"ItemValueLabel": "023",
"Name": "hA"
},
{
"ItemValue": "0005",
"Label": "Manager Identification",
"ItemValueLabel": "0005",
"Name": "hUM"
},
{
"ItemValue": "0005",
"Label": "House Code",
"ItemValueLabel": "0005",
"Name": "hPUM"
}
]
}
]
This is my logic
public ArrayList<Summary> getHouseHoldRecordsByCase(String country, String projectId, String case) {
ArrayList<Summary> documents= new ArrayList<>();
Summary summary = new Summary();
ArrayList<ItemDetails> details = new ArrayList<>();
COVER cover = dataStoreService.getHouseHoldRecordsByCase(country, projectId, caseNumber);
summary.case = caseNumber;
summary.recordType = "Identification";
summary.country = country;
summary.projectId = projectId;
Field[] fields = hsecover.getClass().getDeclaredFields();
for (Field _f:fields){
try {
String val = PropertyUtils.getProperty(hsecover, _f.getName()).toString();
details.add(new ItemDetails(val, _f.getName(), val, _f.getName()));
} catch (Exception e) {
e.printStackTrace();
}
}
summary.itemDetails = details;
documents.add(summary);
summary = new Summary();
ELIGILITY elig = dataStoreService.getEliByCase(country, projectId, case);
summary.recordType = "Eligibility";
summary.case = case;
summary.country = country;
summary.projectId = projectId;
details = new ArrayList<>();
fields = elig.getClass().getDeclaredFields();
for (Field _f:fields){
try {
String val = PropertyUtils.getProperty(elig, _f.getName()).toString();
details.add(new ItemDetails(val, _f.getName(), val, _f.getName()));
} catch (Exception e) {
e.printStackTrace();
}
}
summary.itemDetails = details;
documents.add(summary);
}
return documents;
}
public COVER getHouseHoldRecordsByCase(String country, String projectId, String case) {
COVER usa = cover_repository.findByCase(case);
return usa;
}
public ELIGILITY getEliByCase(String country, String projectId, String case) {
ELIGILITY usa = eligility_repository.findByCaseNumber(case);
return usa;
}
My ItemDetails model class
public class ItemDetails {
public String ItemValue;
public String Label;
public String ItemValueLabel;
public String Name;
public ItemDetails(String itemValue, String label, String itemValueLabel, String name) {
ItemValue = itemValue;
Label = label;
ItemValueLabel = itemValueLabel;
Name = name;
}
}
My Summary class
public class Summary {
public String country;
public String projectId;
public String case;
public String recordType;
public ArrayList<ItemDetails> itemDetails;
}
The data comes from a database.
How can I set the label names with names that make sense instead of coming as entity names?
You Can use #JsonProperty("different names") on each fields
Or you can use #JsonSetter("different name") on setter method level.

Recursive JSON data parsing using GSON

Sometime we may have JSON data like,
[
{
"Name": "Fruits",
"Quantity": "10",
"isCheckBox": false,
"List": [
{
"Name": "Mango",
"Quantiy": "10",
"iScheckBox": true,
"List": null
},
{
"Name": "Apple",
"Quantiy": "10",
"iScheckBox": false,
"List": [
{
"Name": "Simla",
"Quantiy": "10",
"iScheckBox": true,
"List": null
},
{
"Name": "Fuji",
"Quantiy": "10",
"iScheckBox": false,
"List": []
}
]
}
]
},
{
"Name": "Fruits",
"Quantity": "10",
"isCheckBox": false,
"List": [
{
"Name": "Mango",
"Quantiy": "10",
"iScheckBox": true,
"List": null
},
{
"Name": "Apple",
"Quantiy": "10",
"iScheckBox": false,
"List": [
{
"Name": "Simla",
"Quantiy": "10",
"iScheckBox": true,
"List": null
},
{
"Name": "Fuji",
"Quantiy": "10",
"iScheckBox": false,
"List": []
}
]
}
]
}
]
Note : If the isCheckBox value is false then will check the list values to get the inner objects.
Don't know the end of depth level, it may end, or goes on. How to define the POJO class for JSON data like this?
public class Shopping
{
private Fruits Fruits;
private String Vegetables;
public Fruits getFruits ()
{
return Fruits;
}
public void setFruits (Fruits Fruits)
{
this.Fruits = Fruits;
}
public String getVegetables ()
{
return Vegetables;
}
public void setVegetables (String Vegetables)
{
this.Vegetables = Vegetables;
}
#Override
public String toString()
{
return "ClassPojo [Fruits = "+Fruits+", Vegetables = "+Vegetables+"]";
}}
This will be enough for the above given sample. Please try
Actually the solution is very simple,
Here is entity,
public class FruitsEntity {
String Name;
String Quantity;
boolean isCheckBox;
ArrayList<FruitsEntity> List;
}
And you can parse using,
Gson gson = new Gson();
ArrayList<FruitsEntity> nestEntities = gson.fromJson(jsonData, new TypeToken<ArrayList<FruitsEntity>>() {
}.getType());

How to use Retrofit2 to deserialize when JsonArray nested to another JsonArray

Here is my Json data.
[
{
"id": 280866,
"student_id": 7,
"lesson_date_id": 31476,
"recorded_time": "11:49:55",
"lecturer_id": null,
"status": 12895,
"created_at": "2017-07-31 11:49:55",
"updated_at": null,
"lesson_date": {
"id": 31476,
"lesson_id": 28,
"ldate": "2017-07-31",
"updated_by": 1,
"created_at": "2017-04-19 03:33:43",
"updated_at": null
},
"lecturer": null,
"lesson": {
"id": 28,
"semester": "2",
"module_id": "009521",
"subject_area": "IS PDA",
"catalog_number": "7COMISS",
"class_section": "T03",
"component": "TUT",
"facility": "05-04-0009",
"venue_id": 2,
"weekday": "2",
"start_time": "08:00:00",
"end_time": "12:00:00",
"meeting_pattern": "",
"created_at": "0000-00-00 00:00:00",
"updated_at": "2017-07-10 10:19:51",
"lesson_name": null,
"credit_unit": null
}
},
{
"id": 284077,
"student_id": 6,
"lesson_date_id": 31476,
"recorded_time": "00:00:24",
"lecturer_id": null,
"status": -1,
"created_at": "2017-08-01 00:00:23",
"updated_at": null,
"lesson_date": {
"id": 31476,
"lesson_id": 28,
"ldate": "2017-07-31",
"updated_by": 1,
"created_at": "2017-04-19 03:33:43",
"updated_at": null
},
"lecturer": null,
"lesson": {
"id": 28,
"semester": "2",
"module_id": "009521",
"subject_area": "IS PDA",
"catalog_number": "7COMISS",
"class_section": "T03",
"component": "TUT",
"facility": "05-04-0009",
"venue_id": 2,
"weekday": "2",
"start_time": "08:00:00",
"end_time": "12:00:00",
"meeting_pattern": "",
"created_at": "0000-00-00 00:00:00",
"updated_at": "2017-07-10 10:19:51",
"lesson_name": null,
"credit_unit": null
}
},
{
"id": 284076,
"student_id": 5,
"lesson_date_id": 31476,
"recorded_time": "00:00:24",
"lecturer_id": null,
"status": -1,
"created_at": "2017-08-01 00:00:23",
"updated_at": null,
"lesson_date": {
"id": 31476,
"lesson_id": 28,
"ldate": "2017-07-31",
"updated_by": 1,
"created_at": "2017-04-19 03:33:43",
"updated_at": null
},
"lecturer": null,
"lesson": {
"id": 28,
"semester": "2",
"module_id": "009521",
"subject_area": "IS PDA",
"catalog_number": "7COMISS",
"class_section": "T03",
"component": "TUT",
"facility": "05-04-0009",
"venue_id": 2,
"weekday": "2",
"start_time": "08:00:00",
"end_time": "12:00:00",
"meeting_pattern": "",
"created_at": "0000-00-00 00:00:00",
"updated_at": "2017-07-10 10:19:51",
"lesson_name": null,
"credit_unit": null
}
},
{
"id": 284075,
"student_id": 4,
"lesson_date_id": 31476,
"recorded_time": "00:00:24",
"lecturer_id": null,
"status": -1,
"created_at": "2017-08-01 00:00:23",
"updated_at": null,
"lesson_date": {
"id": 31476,
"lesson_id": 28,
"ldate": "2017-07-31",
"updated_by": 1,
"created_at": "2017-04-19 03:33:43",
"updated_at": null
},
"lecturer": null,
"lesson": {
"id": 28,
"semester": "2",
"module_id": "009521",
"subject_area": "IS PDA",
"catalog_number": "7COMISS",
"class_section": "T03",
"component": "TUT",
"facility": "05-04-0009",
"venue_id": 2,
"weekday": "2",
"start_time": "08:00:00",
"end_time": "12:00:00",
"meeting_pattern": "",
"created_at": "0000-00-00 00:00:00",
"updated_at": "2017-07-10 10:19:51",
"lesson_name": null,
"credit_unit": null
}
},
{
"id": 280865,
"student_id": 2,
"lesson_date_id": 31476,
"recorded_time": "11:49:55",
"lecturer_id": null,
"status": 12895,
"created_at": "2017-07-31 11:49:55",
"updated_at": null,
"lesson_date": {
"id": 31476,
"lesson_id": 28,
"ldate": "2017-07-31",
"updated_by": 1,
"created_at": "2017-04-19 03:33:43",
"updated_at": null
},
"lecturer": null,
"lesson": {
"id": 28,
"semester": "2",
"module_id": "009521",
"subject_area": "IS PDA",
"catalog_number": "7COMISS",
"class_section": "T03",
"component": "TUT",
"facility": "05-04-0009",
"venue_id": 2,
"weekday": "2",
"start_time": "08:00:00",
"end_time": "12:00:00",
"meeting_pattern": "",
"created_at": "0000-00-00 00:00:00",
"updated_at": "2017-07-10 10:19:51",
"lesson_name": null,
"credit_unit": null
}
}
]
I use Retrofit2 and can get the correct response when i don't put the lesson_dateand beacon_lesson in my Model.That's means using Retrofit2 ,i can only get the JsonObject in the specific jsonArray. But when there's another JsonArray lesson_date and beacon_lesson is nested in the JsonArray. But if i use the same method in my Model ,it will have no response, even don't have the error message.
Here is my Model class.
public class TimetableResult {
#SerializedName("id")
#Expose
private String id;
#SerializedName("lesson_id")
#Expose
private String lesson_id;
#SerializedName("lecturer_id")
#Expose
private String lecturer_id;
#SerializedName("lesson")
#Expose
private Lesson lesson;
#SerializedName("venue")
#Expose
private Venue venue;
#SerializedName("lesson_date")
#Expose
private LessonDate lesson_date;
#SerializedName("beaconLesson")
#Expose
private LessonBeacon lessonBeacon;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getLesson_id() {
return lesson_id;
}
public void setLesson_id(String lesson_id) {
this.lesson_id = lesson_id;
}
public String getLecturer_id(){return lecturer_id;}
public void setLecturer_id(String lecturer_id){this.lecturer_id=lecturer_id;}
public Lesson getLesson() {
return lesson;
}
public void setLesson(Lesson lesson) {
this.lesson = lesson;
}
public LessonDate getLesson_date() {
return lesson_date;
}
public void setLesson_date(LessonDate lesson_date) {
this.lesson_date = lesson_date;
}
public Venue getVenue() {
return venue;
}
public void setVenue(Venue venue) {
this.venue = venue;
}
public LessonBeacon getLessonBeacon() {
return lessonBeacon;
}
public void setLessonBeacon(LessonBeacon lessonBeacon) {
this.lessonBeacon = lessonBeacon;
}
If i comment the lesson_date &beacon_lesson in the Model, then it can work correctly.And i can get the information. It is very strange.Here is the LessonDate Model.
public class LessonDate {
#SerializedName("id")
#Expose
private String id;
#SerializedName("lesson_id")
#Expose
private String lesson_id;
#SerializedName("ldate")
#Expose
private String ldate;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getLesson_id() {
return lesson_id;
}
public void setLesson_id(String lesson_id) {
this.lesson_id = lesson_id;
}
public String getLdate() {
return ldate;
}
public void setLdate(String ldate) {
this.ldate = ldate;
}
public String getDate()
{
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
Date startDate;
String week_day = null;
try
{
startDate = df.parse(ldate);
week_day = getWeekDay(startDate.getDay());
}
catch (Exception e)
{
e.printStackTrace();
}
return week_day;
}
private String getWeekDay(int day)
{
String strWeekDay = null;
switch (day) {
case 1:
strWeekDay = "Monday";
break;
case 2:
strWeekDay = "Tuesday";
break;
case 3:
strWeekDay = "Wednesday";
break;
case 4:
strWeekDay = "Thursday";
break;
case 5:
strWeekDay = "Friday";
break;
case 6:
strWeekDay = "Saturday";
break;
case 7:
strWeekDay = "Sunday";
break;
}
return strWeekDay;
}
}
Here is the BeaconUser Model.
public class BeaconUser {
#SerializedName("id")
#Expose
private String id;
#SerializedName("major")
#Expose
private String major;
#SerializedName("minor")
#Expose
private String minor;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getMajor() {
return major;
}
public void setMajor(String major) {
this.major = major;
}
public String getMinor() {
return minor;
}
public void setMinor(String minor) {
this.minor = minor;
}
}
Thanks for your time reading my question.
Even if i cant find your nested JsonArray since it's one Json-Array wrapped around multiple Json-Object's you can get the Value using
#GET("path/to/your/data")
List<BeaconUser> Users();
If you have nested JsonArrays then you should modify your Model like:
Class MyModel {
List<MyOtherModel> data;
}
while the nested JSONArray is the List within the Model.
In your case it means that LessonDate is another JsonObject (Object->Object) which is not an array and it should work. Please post the Exception to figure out if there is another issue.

RETROFIT 2.0 unbale to acess api response data contains any list

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

Categories

Resources