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)
Related
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
In my application I get response from server which contains all important information about my received letters. You can see a sample of such response:
{
"count": int, # number of messages
"messages": [ # array of messages
{
"id": int, # message id
"subject": str, # message subject
"can_delete": bool, # can it be deleted (True) or not (False)
"new": int # message already read (0) or not (1)
"date": str, # date of message in 'd.m.y'. If message was sent today format will be 'H:M'
"receiver_name": str, # name of receiver if type=1
"sender_name": str, # name of sender if type=0
}, ...
],
"next_url": URL, # url for get next messages, if no more messages value is null
"previous_url": URL # url for get previous messages, if no more messages value is null
}
and as I understand I have to create a class which will contain all similiar fields and then I will use it for fetching the following information into some adapters. But I can't understand how I have to write these all fields at my class. I have to create all similiar with the sample of my response, like count, or array of messages??? I can't understand the way of creating this array at all, because I saw that I have to insert some data into my array initialization.
Thank you for your positive answers and advices.
To do what you need, you have to create a model (class) with the same structure of your response. Then you can parse it into an object and easily process the datas.
Your model is something like this:
public class MyMessage{
private int id;
private String subject;
private boolean can_delete;
#SerializedName("new") //this is because new is a protected keyword. this annotation is for Gson parsing library. Any library has his own annotation
private int newField;
private String date;
private String receiver_name;
private String sender_name;
public MyMessage(){}
//here getters and setters
}
public class ResponseMessage{
private int count;
private List<MyMessage> messages;
private String next_url;
private String previous_url;
public ResponseMessage() {
}
//here getters and setters
}
Note: obv the class you need to use for json parsing is the ResponseMessage one.
Please note that the new field has some problems with the keyword. You will need to call it in another way and specify the serializedName of that property.
Hope this helps
Edit: I would suggest using Gson. It is really intuitive and easy.
A simple usage for your case would be this:
Gson gson = new GsonBuilder().create();
ResponseMessage myWebResponse = gson.fromJson(inputString, ResponseMessage.class);
Where ResponseMessage is your deserialized object, and inputString is your json string :)
I have json response ,where I have the array & objects with same name. I could not parse it with GSON. Is it impossible to parse that kind of json response with Gson? or, there is some way to parse the response with GSON?
Example of response:
{
"content": [
{
"type": "text",
"content": "adnan",
"class": "32",
"align": "1"
},
{
"type": "image",
"image": "http://adnanul.jpg",
"width": 590,
"content": "sarkar",
"height": 332,
"link": "http://hashtagfail.com/post/44606137082/mobile-services-android-serialization-gson",
"caption": "3",
"class": "332"
}
]
}
The Error -
Exception is: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a string but was BEGIN_ARRAY at line 1 column 26643 path $.data[1].content[27].content
The problem is that, content field inside content field is a array not a String, that is not shown inside your code example, but it is what the exception means. It could be that in some cases content is a String and in some cases an array.
Here is a similar problem and a answer -
Gson - Same field name, different types
Yes it is possible to archive this response.
public class ContentEntity {
private ArrayList<Content> content;
public class Content {
private String type;
private String image;
private int width;
private int height;
private String content;
private String link;
private String caption;
#SerializedName("class")
private String className;
// Add getter and setter here
}
}
try using below entity while parsing it using GSON.
Using default representation will propably cause this because you have keys with same name. Maybe writing an own deserializer will help.
Lets asume that you have a Java class name "Content" and the json-String represents an array of this object:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Content.class, new MyBrandNewContentDeserializer());
Gson gson = gsonBuilder.create();
Content[] conts = gson.fromJson(jsonInput, Content.class);
Within the deserializer you can react on the String type "content"
Try using http://www.jsonschema2pojo.org/ . Just provide your json , select JSON as source type and then select Gson as annotation style. It will generate a POJO class
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.
I've found a few similar issues here and on google, but nothing that seems to match my problem.
here is the JSON being returned from the server:
"{
\"user\":
{\"user_id\":19,
\"user_name\":\"John Doe\",
\"user_token\":\"1412869773.19\",
\"profile_pic\":\"https://graph.facebook.com/12345/picture?type=large\",
\"number_of_creds\":650,
\"level\":10,
\"is_new_user\":false,
\"is_display\":false,
\"gender\":\"male\",
\"zip\":\"05405\",
\"age\":39,
\"numberOfCreditsEarned\":0},
\"success\":true,
\"message\":\"\",
\"extraParameter\":null,
\"user_token\":null
}"
and here is the object I'm trying to map it to:
public class NetworkUserLoginResponseModel {
public UserModel user;
public Boolean success;
public String message;
public String extraParameter;
public String user_token;
}
is it because of the escapes on the quotes ()?
can I not map a JSON string with an embedded object?
TIA
The problem comes from quotes present in your server response, with the latter it's not a valid JSON.
To test JSON string you can use : jsonlint
With no quotes, Gson will successfully parse JSON string into NetworkUserLoginResponseModel object