Deserializing multi-leveled JSON - android

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

Related

Why can't I parse the JSON?

I am sorry for I am a beginner.
I try to put the value into string name[], int age [], int hand[],
but all the value is null.
I don't know which part have problem. Since i learn this from youtube.
I just want to store the data to array.
Thank you
public class main extends AppCompatActivity {
String oName[] = new String [];
int oAge [] = new int [];
int oHand [] = new int [];
protected void onCreate(Bundle savedInstanceState) {...}
private class DownloadTask extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground (String... values) {
InputStream is = null;
String result = ""; //Get json?
String line;
try {
URL ua = new URL("https://api.myjson.com/bins/r5kim"); //json address
HttpURLConnection conn = (HttpURLConnection) ua.openConnection();
conn.setRequestMethod("GET");
conn.connect();
is = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
while ((line = reader.readLine()) != null) {
result += line;
}
is.close();
JSONObject jo = new JSONObject(result); //get json
JSONArray op = jo.getJSONArray("opponents"); //json array?? parse??
for(int i = 0; i < op.length(); i++) {
oName[i] = op.getJSONObject(i).getString("name"); //Get null
oAge[i] = op.getJSONObject(i).getInt("age"); //Get null
oHand[i] = op.getJSONObject(i).getInt("hand"); //Get null
}
} catch (MalformedURLException e) { //exception
e.printStackTrace();
} catch (IOException e) { //exception
e.printStackTrace();
} catch (JSONException e) { //exception
e.printStackTrace();
}
return null;
}
}
Since you didn't post the json string it is hard to determinate what you are doing wrong.
The best advice I can give you is to check out gson library which is the most common json parser on Android (there are obv more, this is the one I use). how to add reference.
Watching videos, searching on google and also here on SO you will find thousands of "how to use gson posts", but anyway I will give you the fastest "how to" for it.
1. Assume you have a string like this:
{
"id":1,
"name":"Little Mouse"
}
2. Create an object matching the one passed by json string
public class MyObject{
private int id;
private String name;
//getters and setters
}
3. Now initialize gson and parse the string to the desired object
//Initialize Gson object with GsonBuilder (you can customize it, you will learn)
Gson gson = new GsonBuilder().create();
//parse your string using an object matching your output
MyObject myObject = gson.fromJson(myJsonString, MyObject.class);
It is pretty simple, but if you need help, ask freely
Post scriptum:
you can obiouvsly parse any kind of class, with also custom parameters and nested classes. You just have to create a model class with the parameters you need written with the same name (or you can explicit the desired name) and with the same property type (int, string, ...)
This is your model:
public class myJsonModel{
private List<Opponent> opponents;
//getters and setters
}
public class Opponent{
private String name;
private String age;
private String hand;
//getters and setters
}
So your result should be
myJsonModel myObject = gson.fromJson(myJsonString, myJsonModel.class);

Android - Retrofit Gson- How to parse JSON String to object at a JSON key in JSON response?

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

How can I serialize a RealmObject to JSON in Realm for Java?

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

Failure to deserialize JSON object

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.

gson to POJO object, not working properly

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

Categories

Resources