Java gson generic array/list deserialization - java

I'm trying to deserialize a generic list using Gson.
I'm able to deserialize the following JSON:
[{"updated_at":"2012-03-09T11:13:31Z","id":1,"title":"Moda","position":0,"short_name":"Md"},
{"updated_at":"2012-03-09T11:13:40Z","id":2,"title":"Sissi","position":1,"short_name":"SI"},
{"updated_at":"2012-03-09T11:13:47Z","id":3,"title":"Levis","position":2,"short_name":"LV"},
{"updated_at":"2012-03-09T11:14:03Z","id":4,"title":"Dolce&Gabanna","position":3,"short_name":"DG"}]
with the following code:
T[] array = (T[])java.lang.reflect.Array.newInstance(p_class, 0);
gson.fromJson(content, array.getClass());
But now, I have the following JSON what I can't figure out how to deserialize with gson:
[{"brand":{"updated_at":"2012-03-09T11:13:31Z","id":1,"title":"Moda","position":0,"short_name":"Md"}},
{"brand":{"updated_at":"2012-03-09T11:13:40Z","id":2,"title":"Sissi","position":1,"short_name":"SI"}},
{"brand":{"updated_at":"2012-03-09T11:13:47Z","id":3,"title":"Levis","position":2,"short_name":"LV"}},
{"brand":{"updated_at":"2012-03-09T11:14:03Z","id":4,"title":"Dolce&Gabanna","position":3,"short_name":"DG"}}]
Thanks for your help!

You need to create a new class which has an object named brand and is a type of p_class. Then use gson on your new class as you did before and it should return you an array of your new class. for example:
class Brand{
private p_class brand;
public p_class getBrand(){
return brand;
}
}
and for gson:
List<Brand> brands = (List<Brand>) gson.fromJson(content, new TypeToken<List<Brand>>(){}.getType());
another way would be doing with ordinary json objects available in android framework:
JSONArray ar = new JSONArray(content);
for(int i=0; i<ar.length(); i++){
JSONObject obj = ar.getJSONObject(i);
//here is your desired object
p_class p = gson.fromJson(obj.getJSONObject("brand").toString(), p_class.class);
}

Related

create json using Google Gson

I want make json
records":[ {"MON_PRIORITY":"","MON_ICR_ACCNO":"100000010010","MON_REPORT_DATE":"","MON_STATUS":"",
But my json is
{"MON_PRIORITY":"","MON_ICR_ACCNO":"100000010010","MON_REPORT_DATE":"","MON_STATUS":"",
My jsp code is
HashMap jsonRecordval = (HashMap) hshValues.get("jsonRecord");
String json="";
json = new Gson().toJson(jsonRecordval );
Thanks..
What you're getting is the JSON produced by a Hashmap. e.g. {"key":"value"}. Breaking it down piece by what, your desired json is a representation of an object { with a records field "records" that contains an array [ of the contents of your hashmap {"key":"value"}
To do that, it's easiest to create an object with instance variables corresponding to the fields to expected output. Something like
public class JsonRecords {
private final List<HashMap> records = new ArrayList<>;
public JsonRecords(HashMap recordsVal) {
records.add(recordsVal);
}
//Getters and setters
}
Then use it to build your JSON
HashMap jsonRecordval = (HashMap) hshValues.get("jsonRecord");
String json = new Gson().toJson(new JsonRecords(jsonRecordval));

How to access JSON Hierarchy in Java

I have the following JSON coming from a server in the variable of StringBuffer called response which I can see in the output after making it toString().
[{"_id": "Grocery", "Categories": [{"Pulses and Grains": ["Dals"]}, {"Beverages": ["Juices", "Tea", "Coffee", "Soft Drinks"]}]}, {"_id": "Stationary", "Categories": [{"Chart Paper": ["A4 Size Chart Paper", "A3 Size Chart Paper"]}]}]
The code I have written till now which is not solving my purpose:
JSONArray ar=new JSONArray(response.
JSONObject jObject = ar.getJSONObject(0);
JSONObject jObject = ar.getJSONObject(1);
String JObjectString=jObject.toString();
System.out.println("The JObject String "+JObjectString);
I need to store each and every element which includes "Pulses and Grains", "Dals", "Tea", "A3 size paper" etc. and every element in that array in a String variable.
How can I access each and every element from the hierarchy since it is too nested.?
Since JSONObject implements the Map interface, you can list all of its field name and values with method
jObject.entrySet()
If you know the name of the fields in advance, you can retrieve them by name:
JSONArray categories = jObject.get("Categories");
But I would rather suggest to use some nice JSON libraries such as google's Gson, so that you can just define your data classes and then automagically parse the JSON into a hierarchy of classes:
class Element {
String _id;
List<Category> categories;
public Element(){}
}
class Category {
private List<Entry> entries;
public Category (){}
}
class Entry {
private List<String> units;
public Entry (){}
}
Then you can parse the json into objects:
Gson gson = new Gson();
Element[] elements = gson.fromJson(jsonString, Element[].class);

How to create json, sorted on keys, using gson?

I need to create constant json string or a json sorted on keys. What do I mean by constant json string? Please look into following code sample, which I created.
My Code 1:
public class GsonTest
{
class DataObject {
private int data1 = 100;
private String data2 = "hello";
}
public static void main(String[] args)
{
GsonTest obj=new GsonTest();
DataObject obj2 = obj.new DataObject();
Gson gson = new Gson();
String json = gson.toJson(obj2);
System.out.println(json);
}
}
Output 1:
{"data1":100,"data2":"hello"}
My Code 2:
public class GsonTest
{
class DataObject {
private String data2 = "hello";
private int data1 = 100;
}
public static void main(String[] args)
{
GsonTest obj=new GsonTest();
DataObject obj2 = obj.new DataObject();
Gson gson = new Gson();
String json = gson.toJson(obj2);
System.out.println(json);
}
}
Output 2:
{"data2":"hello","data1":100}
If you see, if I switch variables (data1 & data2 in DataObject class), I get different json. My objective to get same json, even if somebody changes position of the class variables. I get it when somebody adds new variables, json would change. But json shouldn't change when variables are moved around. So, my objective is to get standard json, possibly in sorted keys order for same class. If there is nested json, then it should be sorted in the nested structure.
Expected output on run of both the codes:
{"data1":100,"data2":"hello"} //sorted on keys!! Here keys are data1 & data2
I understand, I need to change something in String json = gson.toJson(obj2); line, but what do I have to do?
Why I need them to be order?
I need to encode the json string and then pass it to another function. If I change the order of keys, even though value remain intact, the encoded value will change. I want to avoid that.
First of all, the keys of a json object are unordered by definition, see http://json.org/.
If you merely want a json string with ordered keys, you can try deserializing your json into a sorted map, and then serialize the map in order to get the sorted-by-key json string.
GsonTest obj=new GsonTest();
DataObject obj2 = new DataObject();
Gson gson = new Gson();
String json = gson.toJson(obj2);
TreeMap<String, Object> map = gson.fromJson(json, TreeMap.class);
String sortedJson = gson.toJson(map);
Like others have mentioned that by design JSON is not supposed to have sorted keys in itself. You can also come up with a recursive solution to do it. I won't say my solution is very efficient but it does the intended job. Please have a look at the following piece of code.
private static JsonObject sortAndGet(JsonObject jsonObject) {
List<String> keySet = jsonObject.keySet().stream().sorted().collect(Collectors.toList());
JsonObject temp = new JsonObject();
for (String key : keySet) {
JsonElement ele = jsonObject.get(key);
if (ele.isJsonObject()) {
ele = sortAndGet(ele.getAsJsonObject());
temp.add(key, ele);
} else if (ele.isJsonArray()) {
temp.add(key, ele.getAsJsonArray());
} else
temp.add(key, ele.getAsJsonPrimitive());
}
return temp;
}
Input:
{"c":"dhoni","a":"mahendra","b":"singh","d":{"c":"tendulkar","b":"ramesh","a":"sachin"}}
Output:
{"a":"mahendra","b":"singh","c":"dhoni","d":{"a":"sachin","b":"ramesh","c":"tendulkar"}}
Perhaps a work around is for your class wrap a TreeMap which maintains sort order of the keys. You can add getters and setters for convenience. When you gson the TreeMap, you'll get ordered keys.

Serialize objects with Gson into arbitrary JSON arrays without getting warnings

I need to serialize an object like this:
class A {
int a = 1;
String b = "hello";
boolean isDog = false;
}
into JSON array like this:
[1,"hello",false]
I know one (wrong) way to do this: create an untyped Collection out of object's fields and then Gson it:
class A {
// ...
Collection forGson() {
ArrayList col = new ArrayList();
col.add(a);
col.add(b);
col.add(c);
return col;
}
}
new Gson().toJson(new A().forGson());
But it produces a lot of warnings because of untyped collections usage. So is there any way to serialize objects into an array of arbitrary types without getting any warnings?
This is literally "You're doing it wrong". You don't have an array of random things, you have an (A) object. It has nothing in common with the JSON you want to produce.
That being said, if you really wanted to do this, you supply your own Serializer / Deserializer to Gson:
class ASerializer implements JsonSerializer<A>
{
public JsonElement serialize(A t, Type type, JsonSerializationContext jsc)
{
JsonArray ja = new JsonArray();
ja.add(new JsonPrimitive(t.a));
ja.add(new JsonPrimitive(t.b));
ja.add(new JsonPrimitive(t.isDog));
return ja;
}
}
You'd create a JsonDeserializer that did the reverse, creating a A object from the supplied JSON array.
See: https://sites.google.com/site/gson/gson-user-guide#TOC-Custom-Serialization-and-Deserialization for more info.
Then using GsonBuilder you'd tell Gson to use them:
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(A.class, new ASerializer());
builder.registerTypeAdapter(A.class, new ADeserializer());
Gson gson = builder.create();
...

Gson and the argonauts - problem converting javascript array, to json string, to java pojo using gson. Trying to get my structures correct

Here is my json string, that I am acessing in java:
json =
[
{"id":"123456","Data":"skill2","dmlcrud":false},
{"id":"123456","Data":"skill3","dmlcrud":true},
{"id":"123456","Data":"skill14","dmlcrud":true},
{"id":"123321","Data":"skill1","dmlcrud":false},
{"id":"123321","Data":"skill14","dmlcrud":false}
]
I now want to put it in a collection so ideally/theoretically I would want to do:
List<Person> personList = new Gson().fromJson(json, Person.class);
and personList.size() would = 5. I would then loop through personList and preform my relevant actions.
However, my understanding is that I would need to create a container class, which itself contains the person list ? So instead of (public getters/setters removed for brevity, probably syntax errror in there aswell).
Class Person {
private integer id;
private String Data;
private Boolean dmlCrud ;
}
I would actually need something like ?
Class container{
List<Person> personList;
static class Person {
private integer id;
private String Data;
private Boolean dmlCrud ;
}
}
However I would then need to alter the javascript json to be somethign different aswell ? Which seems rather problematic as am I creating the json string from a javascript array, using JSON.stringifier.
Any help gratefully received.
EDIT
the solution I used was to add
public List<Person> personList;
to the person class
and alter the json object so that it was
{ "personList" :
[
{"id":"123456","Data":"skill2","dmlcrud":false},
{"id":"123456","Data":"skill3","dmlcrud":true},
{"id":"123456","Data":"skill14","dmlcrud":true},
{"id":"123321","Data":"skill1","dmlcrud":false},
{"id":"123321","Data":"skill14","dmlcrud":false}
]
}
the gson call can then be
Person person = new Gson().fromJson(json, Person.class);
and the data accessed in a list like so
List<Person> personList = person.getPersonList();
EDIT 2
A second, better, solution is to use this json array
[
{"id":"123456","Data":"skill2","dmlcrud":false},
{"id":"123456","Data":"skill3","dmlcrud":true},
{"id":"123456","Data":"skill14","dmlcrud":true},
{"id":"123321","Data":"skill1","dmlcrud":false},
{"id":"123321","Data":"skill14","dmlcrud":false}
]
and then use
Type listType = new TypeToken<List<SkillsGsonTO>>() {}.getType();
List<Person> personList = new Gson().fromJson(json,listType);
Person person1 = personList.get(0);
where the original class is used
Class Person {
private integer id;
private String Data;
private Boolean dmlCrud ;
}
You could use a Container class but this only makes sense if you need to ship additional properties on the person list. If this is not the case, you could convert to a java.util.List as well. I think you need to specify the "name" of the list property as a root element in your JSON string. So for instance if you're domain object is a List of Person objects, than your JSON root element is: "persons" or "personList". So you're JSON could look something like:
"persons" : {[
{"id":"123456","Data":"skill2","dmlcrud":false},
{"id":"123456","Data":"skill3","dmlcrud":true},
{"id":"123456","Data":"skill14","dmlcrud":true},
{"id":"123321","Data":"skill1","dmlcrud":false},
{"id":"123321","Data":"skill14","dmlcrud":false}
]}
I could be a little bit off with the syntax, but it should be something similar to this. So to summarize:
In your case you can leave you're Person class untouched and gson should be able to create the List persons for you from the JSON string I suggested.
From the Gson API docs:
If the object that your are deserializing is a ParameterizedType (i.e. contains at least one type parameter and may be an array) then you must use the fromJson(String, Type) method. Here is an example for deserialing a ParameterizedType:
Type listType = new TypeToken<List<String>>() {}.getType();
Gson gson = new Gson();
List<String> target2 = gson.fromJson(json, listType);
So in your case it would be:
Type listType = new TypeToken<List<Person>>() {}.getType();
List<Person> persons = new Gson().fromJson(json, listType);
where json is your json string obviously

Categories

Resources