How to access JSON Hierarchy in Java - 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);

Related

How to convert json of fields with values in Arrays into typed List of custom class?

I am trying to deserialize json into my class using java's jackson-databind. The json is formated like this:
sample.json
{
...,
"random" : {
"field1" : ["x1","y1","z1","a1","b1"],
"field2" : ["x2","y2","z2","a2","b2"],
"field3" : ["x3","y3","z3","a3","b3"]
}
}
I want to read this json to List<MyClass> myList of size 5 [xMy,yMy,zMy,aMy,bMy]. MyClass has attributes: String field1, String field2, String field3. xMy element should have list of [x1,x2,x3]. yMy should have list of [y1,y2,y3]. zMy should have list of [z1,z2,z3].
public class MyClass {
private String field1;
private String field2;
private String field3;
...
}
So the result variable will be List<MyClass> myList.
UltraSmartLogic.java code
JsonNode node = new ObjectMapper().readTree(json);
JsonNode randomNode = node.get("random");
ObjectReader reader = new ObjectMapper().readerFor(new TypeReference<List<String>>() {});
List<String> field1ValueList = reader.readValue(randomNode.get("field1"));
List<MyClass> myList = ???
This is just simplified json, real json contains 7 fields and 1000 values for each field.
Goal here is to create 1000 instances of MyClass inside myList. First element should be mapped with x1,x2,x3, second element should be mapped with y1,y2,y3, third - z1,z2,z3 and so on thousand times...
field1ValueList is no use, because this way I will have 7 List variables and 7 for loops iterating 1000 times each plus one more loop to set values into List<MyClass> myList. I believe jackson is more effective and able to deserialize this, I just don't know how. Yet.

Java Jackson Serialize JSON to HashTable

I am trying to serialize a list of JSON blobs and put certain keys into a HashTable during the serialization. Here is an example of my JSON:
[
{
"name": "sally",
"id": 1,
"eye_color": "green"
},
{
"name": "jack",
"id": 2,
"eye_color": "blue"
},
{
"name": "jane",
"id": 3,
"eye_color": "brown"
}
]
What I am looking for specifically is a POJO (or set of POJOs) which can serialize the above JSON like so with Jackson assuming the above JSON is in a file called above_json.json:
MyPOJO pojo = objectMapper.readValue(new File("above_json.json"), MyPOJO.class);
I want the result of the serialization to give me a HashTable (or an Object which encapsulates the HashTable) where the HashTable key is the value of name and the Hashtable value is the value of the corresponding id above.
Assuming we serialized the above JSON in this fashion, I would want to access the HashTable like so:
myTable.get("jane")
result: 3
myTable.get("jack")
result: 2
myTable.get("Jill")
result: null
I know how to serialize basic JSON with Jackson. I have an example like below:
JSON Input:
"Parameter":{
"Name":"Parameter-Name",
"Value":"Parameter-Value"
}
POJO to serialize above simple JSON:
public class Parameter {
#JsonProperty("Name")
public String name;
#JsonProperty("Value")
public String value;
}
But obviously this type of setup does not put the results into a HashTable. I need a POJO like what I have in this example which will serialize JSON directly into a HashTable
I don't think that is possible.
You serialize this json into a list of pojos, and have a utility function to generate the hashtable in the way you desire from the list of pojos.
Create a POJO for holding the properties you are interested in.
#JsonIgnoreProperties(ignoreUnknown = true)
private static class MyPOJO {
#JsonProperty("name")
private String name;
#JsonProperty("id")
private Integer id;
public Integer getId() {
return id;
}
public String getName() {
return name;
}
}
Deserialize the contents of the file into List<MyPOJO>
List<MyPOJO> myPOJO = mapper.readValue(new File(".."), new TypeReference<List<MyPOJO>>(){});
Stream the contents of the map to construct a map whose key is the name and value is the id.
Map<String, Integer> map = myPOJO.stream()
.collect(Collectors.toMap(MyPOJO::getName, MyPOJO::getId));
First of all, you probably don't want to use a HashTable, as it's considered to be an obsolete type (see here).
Either use a HashMap or if you want thread safety, a ConcurrentHashMap or a thread-unsafe Map backed by Collections.synchronized[...] and referenced to within synchronized statements.
Secondly, you can use a TypeReference to de-serialize as your desired type.
Finally, your JSON's syntax is incorrect: it starts with a square bracket ([) and ends with a curly bracket (}), which is technically unparseable.
Assuming you want an array of Maps here (e.g. HashMap<String, String>[]), here is some suitable code, provided you replace the last curly bracket with a square one:
// the map array
Map<String, String>[] map = null;
map = om.readValue(yourFile, new TypeReference<HashMap<String, String>[]>() {});
// prints the de-serialized contents
System.out.println(Arrays.toString(map));
Edit
Since you have now edited your JSON to remove the first square bracket and replace it with a curly bracket, no you can't parse as a Map as is.
Edit 2
Since you have now re-edited your JSON to feature square brackets once again instead of curly brackets in the wrapping object, you can once again de-serialize as a Map[]. Until the next edit, I guess...

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 do I decode a list of string pairs with GSON?

I have a list of categories coming back from a web request, in JSON format. An example might be:
"categories":[["Descriptive Cat 1 Name","cat1label"]]
How would that be represented in the object? I currently have an object called Category, and am using it like:
private List<Category> categories;
The Category object looks something like:
class Category {
private String descrName;
private String label;
.. getters and setters..
}
When attempting to decode with GSON I get this eror:
01-27 21:44:46.149: ERROR/AndroidRuntime(843): com.google.gson.JsonParseException: Expecting array but found object: Category#437d1ff8
Any suggestions? I would also be OK having those come back as a map, although instead of K,V in the JSON results they would be V,K, could it be mapped that way?
It does work if I ditch the Category object all together, and just map it as:
private List<List<String,String>> categories;
But is there a better way to represent that data?
Nick
As #Dante617 correctly pointed, your JSON representation is not correct. The correct representation is
{
"categories": [
{"descrName":"Descriptive Cat Name 1", "label": "cat1Label"},
{"descrName":"Descriptive Cat Name 2", "label": "cat2Label"}
]
}
Now, this can be thought of as a map of "categories" title and list of Category objects. So, the Java object, that maps it, will be Map<String, List<Category>>
If you somehow reformat your string correctly like the one above. Here is how you would parse.
String categories = "{\"Categories\":[{\"descrName\":\"Descriptive Cat 1 Name\",\"label\":\"cat1label\"}, {\"descrName\":\"Descriptive Cat 2 Name\",\"label\":\"cat2label\"}]}";
Gson gson = new Gson();
Type type = new TypeToken<Map<String, List<Category>>>() {}.getType();
Map<String, List<Category>> l = gson.fromJson(categories, type);
System.out.println("l: " + l);
If your Java object looks like this
public class Category {
private String descrName;
private String label;
//no need of getters and setters. Reflection, baby! :)
#Override
public String toString() {
return "<Name:"+descrName+", label:"+label+">";
}
}
The output will show like this
l: {Categories=[<Name:Descriptive Cat 1 Name, label:cat1label>, <Name:Descriptive Cat 2 Name, label:cat2label>]}
I'm not familiar with GSON, but I'm not sure how the application could map the strings to the fields in your object. It seems like you want a JSON structure more like:
"categories": [
{"descrName":"Descriptive Cat Name 1", "label": "cat1Label"},
{"descrName":"Descriptive Cat Name 2", "label": "cat2Label"}
]
That might help in being able to dynamically create the Java objects.
In contrary to what others think, that's not invalid JSON. The [[]] is just a two-dimensional array. In Java terms, it maps as follows:
String json = "{\"categories\":[[\"Descriptive Cat 1 Name\",\"cat1label\"]]}";
Map<String, String[][]> map = new Gson().fromJson(json, new TypeToken<Map<String, String[][]>>(){}.getType());
// ...
or
String json = "{\"categories\":[[\"Descriptive Cat 1 Name\",\"cat1label\"]]}";
Map<String, List<List<String>>> map = new Gson().fromJson(json, new TypeToken<Map<String, List<List<String>>>>(){}.getType());
// ...
Thanks for the input folks. Unfortunately this is a public web service I'm utilizing (the Yelp v2 API) and I can't change the format of the data they are returning. This is what I stuck with for now which is working fine:
private List<List<String>> categories;

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