I'm trying to parse the following JSON string using GSON in my Android app:
{"Links":[{"Name":"Facebook","URL":"http://www.facebook.com/"},{"Name":"Twitter","URL":"http://twitter.com/"},{"Name":"Last FM","URL":"http://www.last.fm/"},{"Name":"Hyves","URL":"http://hyves.nl"},{"Name":"My Space","URL":"http://www.myspace.com/"},{"Name":"YouTube","URL":"http://www.youtube.com/"}]}
When doing this, GSON gives me the following exception:
10-13 11:09:23.103: DEBUG/Error:(752): The JsonDeserializer com.google.gson.DefaultTypeAdapters$CollectionTypeAdapter#44e9e430 failed to deserialize json object
{"Links":[{"Name":"Facebook","URL":"http://www.facebook.com/"},{"Name":"Twitter","URL":"http://twitter.com/"},{"Name":"Last FM","URL":"http://www.last.fm/"},{"Name":"Hyves","URL":"http://hyves.nl"},{"Name":"My Space","URL":"http://www.myspace.com/"},{"Name":"YouTube","URL":"http://www.youtube.com/"}]}
given the type java.util.List<com.sander.app.json.links.Links>
Now I am a complete novice to JSON, so I'm pretty sure I must be doing something wrong.
I'm using this method to parse my JSON:
WebService webService = new WebService("http://*********/GetLinksData");
//Pass the parameters
Map<String, String> params = new HashMap<String, String>();
params.put("iAppID", "59");
params.put("iFormID", "461");
//Get JSON response from server the "" are where the method name would normally go if needed example
// webService.webGet("getMoreAllerts", params);
String response = webService.webGet("", params);
System.out.println("Returns: "+response);
try
{
//Parse Response into our object
Type collectionType = new TypeToken<List<Links>>(){}.getType();
List<Links> alrt = new Gson().fromJson(response, collectionType);
}
catch(Exception e)
{
Log.d("Error: ", e.getMessage());
}
}
And this is my Links class:
public class Links {
public String Name;
public String URL;
public Links(String name, String URL){
this.Name = name;
this.URL = URL;
}
#Override
public String toString(){
return "Name: " + Name + "URL: " + URL;
}}
How might I be able to fix this problem? I have been stuck on this for two days now, and even though I want to learn how to fix things like this by myself, I'm running out of options.
Regards,
Sander
===================================================
Fixed with the help of Raunak:
public class LinkStorer {
public Link Links[];
public Link[] getLinks(){
return Links;
}
public Link getSingleLink(int i){
return Links[i];
}
public static class Link {
public String Name;
public String URL;
public String getName() {
return Name;
}
public String getURL() {
return URL;
}
}}
Call for JSON object:
LinkStorer collection = new Gson().fromJson(response, LinkStorer.class);
for(int i=0; i < collection.Links.length; i++){
System.out.println(collection.getSingleLink(i).getName());
You have the right idea with regards to making a separate class for links, though, it should look something like this
public class Type {
public Link Links[];
public static class Link {
public String Name;
public String URL;
public String getName() {
return Name;
}
public String getURL() {
return URL;
}
}
}
You can then convert your json string into java object like this:
Type collection = new Gson().fromJson(response, Type.class);
Maybe the problem that when you define the format of JSON input. Your program expects the following JSON.
[{"Name":"Facebook","URL":"http://www.facebook.com/"},{"Name":"Twitter","URL":"http://twitter.com/"},{"Name":"Last FM","URL":"http://www.last.fm/"},{"Name":"Hyves","URL":"http://hyves.nl"},{"Name":"My Space","URL":"http://www.myspace.com/"},{"Name":"YouTube","URL":"http://www.youtube.com/"}]
Try to create another POJO
public class LinksSearchResult {
private List<Links> links;
public List<Links> getLinks() {
return links;
}
}
And use fromJSON like this
LinksSearchResult links = new Gson().fromJson(response, collectionType);
Sorry but at this moment i'm unable to try this properly.
Perhaps GSON can only deserialize a JSON object to a standard Java type? In your case, it may be some thing like List<HashMap<String, List<String>>>. Once you have this, you can iterate through the native Java object to generate your custom object.
Related
This my JSON response:
{
"id": 2,
"name": "Test",
"content": "{\"type\": \"status\", \"text\": \"Lorem ipsum dummy text.\", \"id\": 1}"
}
These are model structures:
class TestModel {
public int id;
public String name;
public Content content;
}
class Content {
public int id;
public String status;
public String text;
}
I want to parse content's value directly into my Content model object using Retrofit and GsonConvertor. But currently, I am parsing it as a String value than by using Gson.fromJson() convert to my Content model object. Is there any solution to get my expected result?
When I used to parse it using GsonConverterFactory, Retrofit gives callback in onFailure method with this exception:
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 4 column 19 path $.data[0].content
The issue is with the JSON response, it is not in the correct JSON format. The "content" field should be an object, not a string:
{
"id": 2,
"name": "Test",
"content": {
"type": "status",
"text": "Lorem ipsum dummy text.",
"id": 1
}
}
This will allow either gson.fromJson(response, TestModel.class) or RetroFit with a GsonConverterFactory to parse your response correctly into the corresponding object.
Of course, this only applies if you have the ability to change the JSON response you are receiving. If not, first make sure the person who is in control of the response knows that they are doing it wrong. If nothing changes, then you should be able to work around this by changing the content in TestModel to a String:
class TestModel {
public int id;
public String name;
public String content;
}
class Content {
public int id;
public String type;
public String text;
}
Then parsing each object separately:
TestModel testModel = gson.fromJson(response, TestModel.class);
Content content = gson.fromJson(testModel.content, Content.class);
If the response cannot be changed, another option is to create a TypeAdapter for your Content object:
public class ContentAdapter extends TypeAdapter<Content> {
#Override
public void write(JsonWriter out, Content value) throws IOException {
// TODO: Writer implementation
}
#Override
public Content read(JsonReader in) throws IOException {
if(in.peek() != JsonToken.NULL) {
return fromJson(in.nextString());
} else {
in.nextNull();
return null;
}
}
}
Then add the TypeAdapter to your GSON implementation:
Gson gson = new GsonBuilder()
.registerTypeAdapter(Content.class, new ContentAdapter()).create();
Hope you are using retrofit version 2.1.0, in this version you can choose the parsers of your choice, but in the previous version Gson was inbuilt parser. I assume you need to use Gson. for that you have to set converterFactory as GsonConverterFactory, example is given below.
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
This will add Gson as your json parser.
Check out this tutorial. also read the documentation here.
Dont forget to add this in your gradle
compile 'com.squareup.retrofit2:converter-gson:2.0.2'
import java.util.ArrayList;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class Parser {
public static List<TestModel> JsonParser(String JsonString) {
try {
JSONArray array = new JSONArray(content);
List<TestModel > arrayList = new ArrayList();
for (int i = 0; i < array.length(); i++) {
JSONObject obj = array.getJSONObject(i);
TestModel model = new TestModel();
model.setId(Integer.parseInt(obj.getString("id")));
model.setName(obj.getString("name"));
JSONArray contentArray = newJSONArray(obj.getString("content")));
JSONObject obj1 = contentArray.getJSONObject(1);
Content content = new Content();
content.setId(Integer.parseInt(obj1.getString("id")));
content.setStatus(obj1.getString("status"));
content.setText(obj1.getString("text"));
model.setContent(content);
arrayList.add(model);
}
return arrayList;
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
}
class TestModel {
//Generate Setter Getter for all properties
public int id;
public String name;
public Content content;
}
class Content {
//Generate Setter Getter for all properties
public int id;
public String status;
public String text;
}
I asked this in a different question today but I'm afraid that won't get any solution because of how it was phrased.
I have a json input that has the following data:
As you can see, the option_value item is an Array in one object and a simple string in another object.
How can I make Gson handle this properly? My class has this described as a List object, so it works for the first few items where option_value is an array, but when it becomes a string, the app crashes and I get a json parse exception.
Is there a workaround for this?
UPDATE
Adding the relevant part of my class as requested:
public class Options
{
String product_option_id;
String option_id;
String name;
String type;
String required;
List<OptionValue> option_value;
// get set stuff here
public class OptionValue
{
String product_option_value_id;
String option_value_id;
String name;
String image;
String price;
String price_prefix;
// get set stuff here
}
}
I have a solution for you :) For this purpose, we should use a custom deserializer. Remake your class like this:
public class Options{
#SerializedName ("product_option_id");
String mProductOptionId;
#SerializedName ("option_id");
String mOptionId;
#SerializedName ("name");
String mName;
#SerializedName ("type");
String mType;
#SerializedName ("required");
String mRequired;
//don't assign any serialized name, this field will be parsed manually
List<OptionValue> mOptionValue;
//setter
public void setOptionValues(List<OptionValue> optionValues){
mOptionValue = optionValues;
}
// get set stuff here
public class OptionValue
{
String product_option_value_id;
String option_value_id;
String name;
String image;
String price;
String price_prefix;
// get set stuff here
}
public static class OptionsDeserializer implements JsonDeserializer<Options> {
#Override
public Offer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
Options options = new Gson().fromJson(json, Options.class);
JsonObject jsonObject = json.getAsJsonObject();
if (jsonObject.has("option_value")) {
JsonElement elem = jsonObject.get("option_value");
if (elem != null && !elem.isJsonNull()) {
String valuesString = elem.getAsString();
if (!TextUtils.isEmpty(valuesString)){
List<OptionValue> values = new Gson().fromJson(valuesString, new TypeToken<ArrayList<OptionValue>>() {}.getType());
options.setOptionValues(values);
}
}
}
return options ;
}
}
}
Before we can let Gson parse json, we should register our custom deserializer:
Gson gson = new GsonBuilder()
.registerTypeAdapter(Options.class, new Options.OptionsDeserilizer())
.create();
And now - just call:
Options options = gson.fromJson(json, Options.class);
In my situation, the field with same name is "data":{} or "data":[array_with_real_data]. So the code from accepted answer need to be modified slightly, like this:
#Override
public MyClass deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
MyClass bean = new Gson().fromJson(json, MyClass.class);
JsonObject jsonObject = json.getAsJsonObject();
if (jsonObject.has("data")) {
JsonArray array = jsonObject.getAsJsonArray("data");
if (array != null && !array.isJsonNull()) {
List<Data> data = new Gson().fromJson(array, new TypeToken<ArrayList<Data>>() {}.getType());
bean.realData = data;
}
}
return bean ;
}
hope that helps.
I am implementing a DB for my Application and I am trying "connect" it to my REST interface. The data comes in as JSON and with the new JSON-Support (as of Realm 0.76) I can throw the JSON at my Realm.createObjectFromJson(MyType.class, jsonString) and it creates the appropiate obejcts and RealmLists.
But how can I do the opposite? That is, take a RealmObject and serialize it to JSON? It also should serialize any RealmList inside that object.
Simply, all you need to do is:
Gson gson = //... obtain your Gson
YourRealmObject realmObj = realm.where(YourRealmObject.class).findFirst();
if(realmObj != null) {
realmObj = realm.copyFromRealm(realmObj); //detach from Realm, copy values to fields
String json = gson.toJson(realmObj);
}
to deserialize JSON into RealmObject use on of the following
say you have a class definition like this
#RealmClass
public class Foo extends RealmObject{
private String name;
public void setName(String name){ this.name = name}
public String getName(){ return this.name}
}
and a json payload like this:
String json = "{\"name\":\"bar\"}";
Foo fooObject= realm.createObjectFromJson(Foo.class, json);
//or
String jsonArray = "[{\"name\":\"bar\"},{\"name\":\"baz\"}]";
RealmList<Foo> fooObjects = realm.createAllFromJson(Foo.class, jsonArray);
However the reverse is not natively supported in realm-core. so this is how i work around it. i attempted to use GSON, but ended up writing too many codes that i myself did not understand so i implemented my own adapter like this.The problem is RealmObjects are not 'realm' java.lang.Object.
create an adapter that takes instance of your realm object and return its JSON representation.
example.
public class RealmJsonAdapter{
public JSONObject toJson(Foo foo){
JSONObject obj = new JSONObject();
obj.putString("name",foo.getName());
//if you have more fields you continue
return obj;
}
}
you can now use this adapter in your classes to serialize you RealmObject to
JSON. prefferably you would make the adapter an interface so that you let callers (might be you yourself) pass you the adapter the want to use.
you can then call say, adapter.toJSON(realmObjectInstance). and get your JSONObject implementation
after all you care only about the JSON and not the RealmObject.
NOTE
This solution is a bit oudated. RealmObjects are now real java objects so you should be able to use it with GSON with no problems. Just make sure you are using version 0.89 or later and everything will work fine.
Christian from Realm here.
Realm for Android currently doesn't have any such methods, although the core database actually supports JSON serialisation, so for now you would either have to do it manually or use a 3rd party tool like GSON (caveat, I havn't tested that scenario yet).
Following is how you would do that with GSON library.
Suppose we have the following json reply from the server :
{
"data": [
{
"id": "1",
"name": "John",
"surname": "Doe"
}
]
}
For this Json object we create a helper class with corresponding properties
public class JsonHelperClass {
String id;
String name;
String surname;
public JsonHelperClass() {
}
public JsonHelperClass(String id, String name, String surname) {
this.id = id;
this.name = name;
this.surname = surname;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
}
Now in the following jsonReply is the string containing reply from server
JSONArray jsonArray = new HttpManager().getJsonArrayFromReply(jsonReply);
if(jsonArray == null || jsonArray.length <0){
return;
}
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject json = null;
try {
json = (JSONObject) array.get(i);
} catch (JSONException e) {
return null;
}
Gson gson = new Gson();
JsonHelperClass helperClass = gson.fromJson(json.toString(), JsonHelperClass.class);
createRealmObject(helperClass);
}
public void createRealmObject(JsonHelperClass helperClass){
Realm realm = Realm.getInstance(context);
realm.beginTransaction();
RealmDataObject obj = realm.createObject(RealmDataObject.class);
obj.setId(helperClass.getId());
obj.setName(helperClass.getName());
obj.setSurname(helperClass.getSurname());
realm.commitTransaction();
}
public JSONArray getJsonArrayFromReply(String reply){
JSONArray array = null;
try {
JSONObject jsonResp = new JSONObject(reply);
array = jsonResp.getJSONArray("data");
} catch (JSONException e) {
return null;
}
return array;
}
And the Realm Data Object
public class RealmDataObject extends RealmObject {
private String id;
private String name;
private String surname;
public RealmDataObject() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
}
Try this
private JSONArray convertRealmintoJSONArray(Activity context){
try {
RealmResults<ModelMyCart> results = RealmControllerMyCart.with(context).getBooks();
JSONArray jsonArray = new JSONArray();
for (ModelMyCart myCart : results
) {
JSONObject object = new JSONObject();
object.put(Constants.PRODUCT_ID, myCart.getId());
object.put(Constants.PRODUCT_TITLE, myCart.getProduct_title());
object.put(Constants.PRODUCT_SIZE, myCart.getProduct_size());
object.put(Constants.PRODUCT_SELLINGFEE, myCart.getProduct_sellingfee());
object.put(Constants.PRODUCT_SELLINGFEE, myCart.getShipping_price());
object.put(Constants.PRODUCT_IMAGE, myCart.getProduct_image());
object.put(Constants.PRODUCT_BRAND, myCart.getProduct_brand());
object.put(Constants.PRODUCT_CATEGORY_ID, myCart.getProduct_category_id());
object.put(Constants.PRODUCT_CATEGORY_NAME, myCart.getProduct_category_name());
object.put(Constants.PRODUCT_COLOR, myCart.getProduct_color());
object.put(Constants.PRODUCT_COLORTYPE, myCart.getProduct_colortype());
object.put(Constants.PRODUCT_CONDITION, myCart.getProduct_condition());
object.put(Constants.PRODUCT_CREATED_DATE, myCart.getProduct_created_date());
object.put(Constants.PRODUCT_MYSALEPRICE, myCart.getProduct_mysaleprice());
object.put(Constants.PRODUCT_ORIGINALPRICE, myCart.getProduct_originalprice());
object.put(Constants.PRODUCT_POTENTIALEARNINGS, myCart.getProduct_potentialearnings());
object.put(Constants.PRODUCT_SHIPPINGCHARGES, myCart.getProduct_shippingcharges());
object.put(Constants.USER_ID, myCart.getUser_id());
object.put(Constants.USER_UNAME, myCart.getUser_uname());
jsonArray.put(object);
}
Log.e("Converted",""+jsonArray);
return jsonArray;
}catch (Exception e){
}
return null;
}
For my case new Gson().toJson(realm.copy(realmObj)); causes UI freezing (sometimes out of memory exception). So I updated my Gson instance like that
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
String jsonString = gson.toJson(realm.copy(realmObj));
I am completely new to the concept of JSON, and am having trouble figuring out how to deserialize a multi-leveled JSON statement using Gson.
This is what I'm trying to deserialize: {"stat":"ok","pkey":{"id":"1234567890"}}
First I tried doing using a hashmap:
HashMap<String, Object> results = gson.fromJson(response, HashMap.class);
The result looked reasonable enough, but the second entry in the hashmap (the one that contained the actual id number) was a gson.internal.LinkedTreeMap, which I couldn't access.
Next I tried making a custom class to deserialize it into, but I can't seem to get it to work right...
Neither of these worked:
class Results
{
String stat;
String[][] pkey;
}
class Results
{
String stat;
String[] pkey;
}
The only examples I can find online have to do with deserializing simple, one level JSON, which looks easy. I just can't seem to figure this out.
Use JSONObject can easy deserializing multi-leveled JSON
This is Log "ok" and "1234567890" from your example
String json = "{\"stat\":\"ok\",\"pkey\":{\"id\":\"1234567890\"}}";
try {
JSONObject jsonObj = new JSONObject(json);
Log.i("chauster", jsonObj.getString("stat"));
Log.i("chauster", jsonObj.getJSONObject("pkey").getString("id"));
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
This is code for gson, you need to custom your class
public class Custom {
private String stat;
private IdClass pkey;
public String getStat() {
return stat;
}
public IdClass getPkey() {
return pkey;
}
public Custom(String _stat, IdClass _pkey) {
stat = _stat;
pkey = _pkey;
}
public class IdClass {
private String id;
public String getId() {
return id;
}
public IdClass(String _id){
id = _id;
}
}
}
String json = "{\"stat\":\"ok\",\"pkey\":{\"id\":\"1234567890\"}}";
Gson gson = new Gson();
Custom custom = gson.fromJson(json, Custom.class);
System.out.println(custom.getStat());
System.out.println(custom.getPkey().getId());
I am developing an Android application and I access a RESTfull web service that returns a JSON. This JSON I want to put it in POJOs but I think I am missing something as it doesn't work.
The JSON retuned is as follow:
[{"CategoryName":"Food","Id":1},{"CategoryName":"Car","Id":2},{"CategoryName":"House","Id":3},{"CategoryName":"Work","Id":4}]
this is returned in response variable
String response = client.getResponse();
And now I try the following:
GsonBuilder gsonb = new GsonBuilder();
Gson gson = gsonb.create();
JSONObject j;
MainCategories cats = null;
try
{
j = new JSONObject(response);
cats = gson.fromJson(j.toString(), MainCategories.class);
}
catch(Exception e)
{
e.printStackTrace();
}
The error I get is:
09-02 07:06:47.009:
WARN/System.err(568):
org.json.JSONException: Value
[{"Id":1,"CategoryName":"Food"},{"Id":2,"CategoryName":"Car"},{"Id":3,"CategoryName":"House"},{"Id":4,"CategoryName":"Work"}]
of type org.json.JSONArray cannot be
converted to JSONObject
09-02 07:06:47.029:
WARN/System.err(568): at
org.json.JSON.typeMismatch(JSON.java:107)
Here are the POJO objects
MainCategories.java
public class MainCategories {
private List<CategoryInfo> category;
public List<CategoryInfo> getCategory() {
if (category == null) {
category = new ArrayList<CategoryInfo>();
}
return this.category;
}
}
CategoryInfo.java
public class CategoryInfo {
public String categoryName;
public Integer id;
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String value) {
this.categoryName = ((String) value);
}
public Integer getId() {
return id;
}
public void setId(Integer value) {
this.id = value;
}
}
To access the web service I use the class from: http://lukencode.com/2010/04/27/calling-web-services-in-android-using-httpclient/
Please help me as I am stuck for 2 days now and can't figure out how to continue. I found some subjects here but still didn't found a way around. Thank you very much.
Top level entity in your JSON string is JSONArray not JSONObject, while you're trying to parse it as object. Create an array from the string and use that.
JSONArray array = new JSONArray(response);