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
Related
I am using gson lib to create json from objects. Backend developers are asking to create all values should be in "" quotes event int/long/boolean fields. For example my json looks like that:
{
"age": 26,
"email": "norman#futurestud.io",
"isDeveloper": true,
"name": "Norman"
}
-> i need the following format:
{
"age": "26",
"email": "norman#futurestud.io",
"isDeveloper": "true",
"name": "Norman"
}
Should i change all my fields from int to String or is there any way to do that? Thanks in advance!
To achieve this only way is to store Int as String and then converting the Data class to json String.As Gson use auto typecasting, you can't tell Gson to convert int to String and give you json.
Create the POJO according to your output json that is the only go.
Your code is JavaScript object literal, not a JSON.
Well try this out!
var obj = {"age": 26,"email": "norman#futurestud.io", "isDeveloper":
true, "name":
"Norman"};
for (var k in obj) {
if (obj.hasOwnProperty(k))
{
obj[k] = String(obj[k]);
}
}
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 want to parse array inside object through GSON.. for Example
{
'title': 'Java Puzzlers: Traps, Pitfalls, and Corner Cases',
'isbn': '032133678X',
'authors':[
{
'id': 1,
'name': 'Joshua Bloch'
},
{
'id': 2,
'name': 'Neal Gafter'
}
]
}
I am only able to parse only object i.e. title, ISBN and got its value but i don't know how to get the value of authors? Please help ,I am using JSON parsing through GSON in android..
ArrayList<Authors> lAuthors = new ArrayList<Authors>();
List<Authors> list = new Gson().fromJson(json, lAuthors.getClass());
for (Object a : list)
{
System.out.println(a);
}
This will give you values in class Author's object.
public class Author{
int id;
String name;
//getter setter here
}
Hope it helps.
those are usefull links for Nasted JSON parsing examples :
Parsing JSON nested array with GSON on Android
http://www.javacreed.com/simple-gson-example/
I have a problem creating a mapping for a json that i want to parse using json. It's very specific, its about a json file with a json array with objects in it.
my jsonfile starts like this:
[
{
"venue": {
"venue_seasons": [
{
"created_at": "2011-12-25T23:00:28Z",
"updated_at": "2011-12-28T15:13:53Z",
"start_timestamp": 1293840000,
"id": 337,
"end": "2011-12-24T00:00:00Z",
"enabled": true,
"start": "2011-01-01T00:00:00Z",
"season_openings": [ … ],
"end_timestamp": 1324684800
},
{ … }
],
"address": "someadress",
"city": "cityname",
"name": "name",
"created_at": "2011-03-31T07:55:33Z",
etcetera
}
"venue":{another venue
So first an array, than an object (venue) with a lot of objects in it (i removed most of them, because thats not important for my question), and some arrays (like season_openings).
My parsing code works like this, im using gson. The inputstream works fine.
Reader reader = new InputStreamReader(inputStream);
JsonResponse venueResponse = gson.fromJson(reader, JsonResponse.class);
List<Venues> results = venueResponse.venue;
with the class JsonResponse:
public class JsonResponse {
public List<Venues> venue;
}
and Venues.class:
public class Venues {
public List<VenueSeasons> venue_seasons;
#SerializedName("adress")
public String getAdress;
#SerializedName("city")
public String getCity;
#SerializedName("country")
public String getCountry; etcetera
}
But when i run this code i get an error:
Unable to start activity ComponentInfo{com.hera.android.JSON/com.hera.android.JSON.TestParser2Activity}: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2
Ofcourse i can read the error: it expects an objects but get an array. I varied a lot with different jsonresponse.class and even with putting the whole json array in a json object (what is not really a solution because i need to work with this type of jsonfile). But everytime i get this or a similar error.
I think I'm close to a solution, can anyone see what i just can't and give me a helping hand?
Thanks.
Try calling Gson like this:
List<Venues> venues = gson.fromJson(reader, new TypeToken<List<Venues>>() {}.getType());
This works because your JSON document is a List, not an object that has a list as one of its properties.