I am parsing the JSON response in retrofit model classes.
My issue is that the response is not constant means some time it will come with 2 params and some time more than that,
exp:
1st response:
{
"error": true,
"data": {
"order_id": [
"Order Id does not exists"
]
},
"code": 500
}
2nd response :
{
"error": false,
"data": [
"Order #P have sent successfully"
],
"code": 200
}
So in first response if the order id is not there than in response i will get order_id as a key but in 2nd response I will not get because it is success.
*** I can solve this issue by asking the back end guy to change the response but if in case, any other prefixed api response, if I will get this kind of result then how will I handle that??
You can use model class like this :
public class ResponseModel {
private boolean error;
private int code;
private JsonElement data;
// Setters, getters, etc. ...
}
Then you can check for error and code value and handle data object in the way you like. Both cases you mention will work with this model.
You can even serialize this data variable to some another model class when you will know what data you have inside.
For this case you should write custom Deserializer and check if data is array or jsonobject.
IMHO in general the idea of using same key for holding error info and non-error info is bad.
Related
I want to parse a Json string from a web-api. Here is it:
{
"RANDOM_ID": {
"lnk_typ": "pdf",
"lnk_description": "Description 1",
"lnk_link": "https://example.com",
"direktdownload": "https://example.com/download1"
},
"RANDOM_ID": {
"lnk_typ": "lnk",
"lnk_description": "Description 2",
"lnk_link": "https://example.com",
"direktdownload": "https://example.com/download2"
}
}
Now my problem:
RANDOM_ID could be every positive number, so it could be 230 or 5 (or
every other positive number).
Also the number of objects can change, i
mean there could more than just 2 RANDOM_ID-Objects.
And i want to know, how to parse this Json. I prefer to do this with Gson, but it could be parsed manual too, if there is a way to do this.
You need to have a class that represent your json string
You can do it manually or generate it with : http://www.jsonschema2pojo.org/ ( set your package name, a class name, choose json as source type and gson as annotation style )
Then you can get item from object like this :
MyObject.getLnkTyp();
I have a json in which 1 key is coming as jsonArray if it has data otherwise it is coming as empty string. It is giving error while parsing in gson with retrofit.
"section": "Technology",
"subsection": "",
"title": "Depiction of Amazon Stirs a Debate About Work Culture",
"abstract": "Details of working conditions at Amazon led to a response from employees, relatives and friends.",
"url": "http://www.nytimes.com/2015/08/19/technology/amazon-workplace-reactions-comments.html",
"byline": "By THE NEW YORK TIMES",
"item_type": "Article",
"updated_date": "2015-08-18T07:35:33-5:00",
"created_date": "2015-08-18T07:35:35-5:00",
"published_date": "2015-08-19T04:00:00-5:00",
"material_type_facet": "News",
"kicker": "",
"des_facet": [
"Workplace Environment"
],
"org_facet": [
"Amazon.com Inc"
],
"per_facet": "",
"geo_facet": "",
des_facet , org_facet, per_facet, geo_facet are jsonArray but you can see that 2 are not having data so coming as empty string.
How to handle this scenario with retrofit +gson.
Json format can't be changed here at server.
is there any way I can achieve it in android?
Ok so there are two option you can solve this
Option 1:
JSON which I used as a example
"des_facet": [
"Workplace Environment"
],
"org_facet": [
"Amazon.com Inc"
],
"per_facet": ["Akshay"],
"geo_facet": ""
In your model class convert those variable to Object type
#Expose
#SerializedName("geo_facet")
private Object geo_facet;
#Expose
#SerializedName("per_facet")
private Object per_facet;
then where you want to set data do the following
if (model != null)
{
if (model.getGeo_facet() != null || model.getGeo_facet() != "")
{
Object arr = model.getGeo_facet();
}
if (model.getPer_facet() !=null || model.getPer_facet()!= "")
{
Object arr = model.getPer_facet();
if (arr!=null && arr.toString().length()>0)
{
arr = arr.toString();
Log.d("akshay","arr= "+arr);
//Do your Stuff or Set data
}
}
}
This is the output= 08-11 16:51:29.830 17951-17951/com.android.example
D/akshay: arr= [Akshay]
Option 2:
Follow this which is a little bit complex
Option 3:
Write own custom Parsing like this and Handle your response accordingly
a json can have a single structure. From the code it is clear that the key is given with 2 types of data
Ideally, it should not give "" when no items. It should give null
Please change the data
If no items,
"des_facet"=null // this is the change on server side. No need to change it on app side
If it has items
"des_facet"=[
"Workplace Environment"
]
instead of
If no items,
"des_facet"=""
If it has items
"des_facet"=[
"Workplace Environment"
]
You can use AutoValue with gson plugin and mark the field as nullable which will notify the Autovalue to make this field optional.
AZs an example this is how you do it:
#AutoValue
public abstract class NewsResponse{
public static TypeAdapter<NewsResponse> typeAdapter(Gson gson){
return new AutoValue_NewsResponse.GsonTypeAdapter(gson);
}
#SerializedName("api_status")
public abstract String apiStatus();
#SerializedName("api_text")
public abstract String success();
#Nullable
#SerializedName("errors")
public abstract ErrorDetails errorDetails();
#SerializedName("news")
public abstract List<NewsDetails> newsDetails();
}
you must import both of them see more info about importing at: AutoValue and AutoValue Gson Plugin
I am using Realm as mobile database and LoganSquare to parse the json data.
i want to parse below mentioned json block return from third party service.
{
"code": 406,
"message": "Not Acceptable",
"errors": [
"Invalid date range: End date is before start date."
]
}
but not sure how would i parse array of error and design error model that has no property name.
Based on at least one example, I am pretty convinced that you could create some class like
#JsonObject
public class MyError {
#JsonField
public int code;
#JsonField
public String message;
#JsonField
public List<String> error;
}
and use it as MyError error = LoganSquare.parse(jsonString, MyError.class); (inspiration from Parsing JSON)
I am working on JSON response . I want to store JSON response in model then store the model values into DB.
So that I used GSON to parse the JSON response.
In my response I have some dynamic JSON array names. The sample and part of the response is below.
{
"TD": [
{
"TimeClockDetails": {
"March 2, 2016": [
{
"TimeclockId": "148148",
},
]
}
In that response , I have the ""March 2, 2016":" array . If a static array name means I can use #SerializeName("arrayname_in_response").
Now, how can I deserialize this dynamic array name ?
If need more clarification,I am ready to provide.
One solution would be to use a Map.
#SerializedName("TimeClockDetails")
private Map<String, TimeDetail> mTimeClockDetails;
This way the date keys would end as keys in the map.
I've written some code to parse the Google Distance Matrix JSON response received by my Android program. The only piece of data I'm interested in is in the "distance" "value" node.
My code works, but it seems like there must be an easier way to do this. The distance value node is nested pretty deep inside the JSON, but is it really necessary to go through every layer of the JSON to get to the field you want?
Here's my JSON response:
{
"destination_addresses" : [
"5660 Baltimore National Pike, Ingleside Shopping Center, Catonsville, MD 21228, USA"
],
"origin_addresses" : [ "Hilltop Cir, Baltimore, MD 21250, USA" ],
"rows" : [
{
"elements" : [
{
"distance" : {
"text" : "3.1 mi",
"value" : 4922 <--THE FIELD I WANT TO EXTRACT
},
"duration" : {
"text" : "11 mins",
"value" : 666
},
"status" : "OK"
}
]
}
],
"status" : "OK"
}
And here is the code I used to pull out the distance value:
private double extractDistance(JSONObject json) {
JSONArray rowsArray = null;
double distanceInMiles = -1;
try {
// Getting Array of Distance Matrix Results
rowsArray = json.getJSONArray("rows");
JSONObject rowsObject = rowsArray.getJSONObject(0);//only one element in this array
JSONArray elementsArray = rowsObject.getJSONArray("elements");
JSONObject elementsObject = elementsArray.getJSONObject(0);//only one element in this array
JSONObject distanceObject = elementsObject.getJSONObject("distance");
distanceInMiles = (distanceObject.getDouble("value"))/1609.344; //distance in meters converted to miles
}
catch (JSONException e) {
e.printStackTrace();
}
return distanceInMiles;
}
Thanks!
I recommend you GSON (http://code.google.com/p/google-gson/) which parse the JSON text into a java class instance, and can convert the class instance to JSON text
Jackson is another good third party parser http://jackson.codehaus.org/. Looks like there's a comparison here, http://www.cowtowncoder.com/blog/archives/2009/09/entry_326.html.
Here's an example traversing using a tree, not sure if it qualifies as easier then what you are already doing, http://wiki.fasterxml.com/JacksonTreeModel
Unless you want to go into writing a custom regular expression to search the json string, yes that's going to be the best way of accessing it (and the easiest). Is there a reason you feel you need to access it 'more efficiently'?
If you are willing to include a third party library you might check out http://code.google.com/p/json-path/ .
I know what you feel right now, I had / have same issues with JSON parsing on android where we dont have #getValueforKey kind of features which is embedded on iOS, Even its so obivious google should realize it now, But there is good work done on Gson lib., look for Google Gson Here for easy way to parse json
Here is nice tute : Gson tute