Deserializing JSON strings using GSON in Android - java

This might be a bit long so please bear with me..
I'm working on a project in Android. I have a JSON string that i need to deserialize into objects representing the JSON structure, the JSON string is something like below:
{"parents":[
{"parent":{
"id":1,
"name":"Sam",
"childs":[
{
"child":{
"id":1,
"name":"Alice",
"books":[
{
"book":{
"id":1,
"name":"Alice in Wonderland"
}
}
]
}
}
]
}
}
]}
Note that for arrays there are repeating values (i.e. many parent and many child) i just put one line here to make it short.
With this i created classes to accomodate the structure:
public class Containers{
private List<Parent> parents;
//setter and getter..
}
public static class Parent extends CommonItem {
private List<Child> childs;
//setter and getter..
}
public static class Child extends CommonItem {
private List<Book> books;
//setter and getter..
}
public class CommonItem{
private int id;
private String name;
//setter and getter
}
Note that i'd created a common class to accommodate the repeating attributes.
Below is how i parse them using GSON:
Gson gson = new Gson();
Containers parents = gson.fromJson(jsonString, Containers.class);
After parsing (there're no error) i try to retrieve the objects. The number of object count in the parents list is correct (i.e. there are 5 parents in the JSON string, and there are 5 Parent objects in the parents List). However, all their attributes are not there, and the child tree are missing as well.
I'd tried numerous configuration, including remove the extended class and put all the id and name in the respective classes but the result is still the same.
Anyone can give me any pointer that where did i go wrong?
Thanx a bunch!

Your JSON and Java class mismatch.
Lets read
{"parents":[
{"parent":{
"id":1,
"name":"Sam",
"childs":[
{
"child":{
"id":1,
"name":"Alice",
"books":[
{
"book":{
"id":1,
"name":"Alice in Wonderland"
}
}
]
}
}
]
}
}
]}
Your top object has a List of class that has parents as it's attribute. Your Java class Container has parents attribute. Good.
Now this list parents is a List of objects that has parent attribute. Does your Parent object has parent attribute? No.
Go further down, each Parent has id, name, and a List of objects as childs (children, should be) attribute that has child attribute, does your Child class has it? No.
Similarly, goes for books.
Did you try your classes on JSON like
{"parents":[
{
"id":1,
"name":"Sam",
"childs":[
{
"id":1,
"name":"Alice",
"books":[
{
"id":1,
"name":"Alice in Wonderland"
}
]
}
]
}
]}

Related

Deserialize JSON With Only Canonical Type String Using Jackson

I have a JSON string
{
"type": "com.example.model.Person",
"data": {
"firstName": "Bob",
...
}
}
That is represented by the following class.
public class Container<T> {
private String type;
private T data;
// Getters and Setters
}
(I've even tried just removing the generic type and replacing it with Object.)
I have tried the following:
new ObjectMapper().readValue(json, Class.forName(canonical))
new ObjectMapper().readValue(json, TypeFactory.defaultInstance().constructFromCanonical(canonical))
I need to be able to deserialize the JSON string into a Container<T> instance with only the given canonical type string. How can this be done?
I tried the same example and its working for me
Is it the same you are looking for or something else

Mapping JSON to Java Class using Jackson

I have a scenario where at run time depending upon the JSON values I have to convert them to choose which JAVA classes we have to use to initialize them.
Below are the two JSON examples
JSON Example1:
{
"parentVal1" : "parent Val 1",
"parentVal2" : "parent val 2",
"childVal1" : "child Val 1",
"childVal2" : {
"childPropVal1" : "child prop 1",
"grandChild" : {
"maleGrandChildVal1" : "male grand child 1",
"maleGrandChildVal2" : "male grand child 2"
}
}
}
JSON Example2:
{
"parentVal1" : "parent Val 1",
"parentVal2" : "parent val 2",
"childVal1" : "child Val 1",
"childVal2" : {
"childPropVal1" : "child prop 1",
"grandChild" : {
"femaleGrandChildVal1" : "female grand child 1",
"femaleGrandChildVal2" : "female grand child 2"
}
}
}
Now, corresponding JAVA classes which I made and class diagram are
public class Parent{
private String parentVal1;
private String parentVal2;
//getters and setters
}
public class Child extends{
private String childVal1;
private ChildProperty childVal2;
//getters and setters
}
public class ChildProperty{
private String childPropVal1;
private GrandChildAbstract grandChild;
//getters and setters
}
public class GrandChildAbstract{
}
public class MaleGrandChild extends GrandChildAbstract{
private String maleGrandChildVal1;
private String maleGrandChildVal2;
//setters and getters
}
public class FemaleGrandChild extends GrandChildAbstract{
private String femaleGrandChildVal1;
private String femaleGrandChildVal2;
//setters and getters
}
The problem is on the runtime I will get a JSON and have to decide whether it belongs to MaleGrandChild or FemaleGrandChild depending upon the ChildProperty.childPropVal1 that I get from JSON.
Can anyone help me are there any way which could initialize the ChildProperty.grandChild property with the respective FemaleGrandChild or MaleGrandChild object.
I am using Jackson for conversion from JSON to JAVA.
Did you read about polymorphic deserialization with Jackson? http://wiki.fasterxml.com/JacksonPolymorphicDeserialization.
Usually you provide the type using JsonTypeInfo. That allows Jackson to understand how to map a specific object.
If you can't really do any manipulation on the JSON (if not sourced by you, for example), you can write a custom mapper (not straightforward) or you can those properties to a simple Map, and let another part of your application deal with the type.

How can I create a JSON object given a schema and object

I have an object that I'd like to generate a JSON object for.
Currently I have an object that is wrapped by another object, a ResourceObject.
This resource object only has a subset of the exposed variables on the top level object.
I use this resource object to generate the json by annotating it. This is to keep the original object cleaner as it's used in other places in the code. However, maintaining this filtering code increases complexity and is mostly boilerplate code.
Ideally, I'd like to pass the object and the expected schema to do the filtering for me, but I don't see anything like that available. I'm hoping my search criteria is just not correct.
Example Class1
Class1 {
private String name = "C1";
private String version = "1.0";
public String getName() {
return name;
}
public String getVersion() {
return version;
}
}
Example Resource class
ResourceClass1 {
private Class1 class1;
ResourceClass1 (Class1 c1) {
class1 = c1;
}
public String getName() {
return class1.getName();
}
}
Example Schema
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Class1",
"type" : "object",
"properties" : {
"name" : {
"type" : "string"
},
}
}
Right now, getting the JSON from the Resource class gives me something to the affect of:
{
"properties" : {
"name" : "C1"
},
}
Is there a package which would get me the same json by passing in only the schema and java object?

Using Gson to parse Json array and object with no name

I know there are many JSON with GSON questions but none of them relate to me directly. My JSON is formatted differently.
I have a JSON data I want to parse using GSON which looks like the following:
[
{
"foo":"1",
"bar":[ { "_id":"bar1"} ],
"too":["mall", "park"]
}
]
And I have the model Classes:
ItemArray Class
public class ItemArray
{
List<Item> itemArray;
//Get set here
}
Item Class
public class Item
{
String foo;
List<Bar> bar;
List<String> too;
//Get set here
}
Bar Class
public class Bar
{
String id;
//Get set here
}
Heres the question. Is the JSON in the correct format? If so, are the model classes in the correct format?
If not, please shove me in the right direction. Thank you in advance!
PS. I can modify the JSON data format if need be.
According to your json, you should simply have :
public class ItemArray extends List<Item> {
}
if you want to keep you java class and change your json it should be :
{
itemArray: [
{
"foo":"1",
"bar":[ { "_id":"bar1"} ],
"too":["mall", "park"]
}
]
}
Oh, and there is a mismatch with the id and _id for Bar :
public class Bar
{
String _id;
//Get set here
}
You could also use an annotation to change the field's name during Json de/serialization.
And last but not least, consider typing your values better. Don't see any data as strings if they are not, you will not a lot of processing in java code to convert things. For instance :
"foo" : 1,
and see foo as an int data member, not a String.
Some times we get JsonArray [ {..} , {..} ] as a response (without 'itemArray' name like yours)
In that case you can use following code
Type fooType = new TypeToken<ArrayList<Item>>() {}.getType();
List<Item> array = new Gson().fromJson(response, fooType);
find more about this Official doc - Gson Array-Examples
If you have a JsonArray like [ {..} , {..} ] you can do this with Gson:
Item[] items = gson.fromJson(json, Item[].class);
To check Json is valid use this tool http://jsonlint.com/
Class Bar(
private String _id;
//create getter/setters
{
public class Item
{
String foo;
List<Bar> bar;
List<String> too;
//Get set here
}
//this is also fine
public class ItemList
{
List<Item> itemArray;
//Get set here
}
you named of list of items "itemArray", but in your json you have not named the corresponding array of items "itemArray".
So make it itemArray, The problem is not in your json, it is valid. Problem is in its representation for Gson,
Gson map keys of json on the variables of object (i.e Java POJO) with same name.
If the name of your list is Class is
List<Item> itemArray;
then the corresponding json array name should also be itemArray, take a look blow
{
itemArray: [
{
"foo":"1",
"bar":[ { "_id":"bar1"} ],
"too":["mall", "park"]
}
]
}
so you can convert json into object like that
Reader reader = new InputStreamReader(IOUtils.toInputStream(json_string));
ItemList itemList = json.toObject(reader, ItemList.class);
Take a look into blow reference for more details
https://stackoverflow.com/questions/13625206/how-to-parse-the-result-in-java/13625567#13625567

Comparing Linked-objects

I have some data from server which looks like this. Each row is an array so the data comes as an array of arrays:
net Person age
net Person height
net Address streetname
org Company name
org Company location
com School color
com School number
From left to right I loop through the array with two for loops and build a tree-like structure of each row(each element is a parent of its follower) like below. After each inner loop i add that particular tree(row tree-like) to the an ArrayList. So each object in the ArrayList is like a tree. As you can see below.
+net
Person
age
+net
Person
height
+net
Address
streetname
+org
Company
name
+org
Company
location
+com
School
color
+com
School
number
This is my main question
After I have added the first object to the ArrayList, I would like to compare the subsequent objects in order to prevent duplicates. As you can see "Person" and "Address" has the same parent "net" so I would like both to be under the same parent so that there will be a single "net". You can also see that "age" and "height" also has the same parent "Person", I want both to go under "Person". "Company" will be under a single "org" and their children "name" and "location" will be under "Company".
How can I compare them to achieve this behaviour?
I implemented the tree-like structure in a form like a linked list as you have spotted already.
//SUPER CLASS
public class Model {
protected String name;
protected Model parent = null;
protected ArrayList<Model> children;
public Model(String name ){
this.setName(name);
children = new ArrayList<Model>();
}
public void addChild(Model node) {
children.add(node);
}
public ArrayList<Model> getChildren() {
return children;
}
}
// SUBCLASSES
public class cPackage extends Model{
public cPackage() {
super();
}
}
public class cClass extends Model{
public cClass () {
super();
}
}
public class cMethod extends Model{
public cMethod () {
super();
}
}
Each element in a row belongs to one of these subclasses. Each level of a the tree belongs to the same class.
My main question now is, how can I compare them efficiently and bring the required objects under their appropriate parent?
Please I need your ideas. If there is a code also I will appreciate that you add it to your suggestions or point me there.
Thank you all.
If you override .equals and .hashCode, you could use a Set (HashSet implementation) to do an O(1) lookup. I would recommend, like mmyers, that you look into some data structures - Java has many of them that are designed for more specialied things.

Categories

Resources