Parsing nested JSON - java

I have the following JSON:
{
"registration": {
"name": "Vik Kumar",
"first_name": "Vik",
"last_name": "Kumar",
"bloodGroup": "B-",
"gender": "male",
"birthday": "10\/31\/1983",
"email": "vik.ceo\u0040gmail.com",
"cellPhone": "1234123456",
"homePhone": "1234123457",
"officePhone": "1234123458",
"primaryAddress": "jdfjfgj",
"area": "jfdjdfj",
"location": {
"name": "Redwood Shores, California",
"id": 103107903062719
},
"subscribe": true,
"eyePledge": false,
"reference": "fgfgfgfg"
}
}
I am using the following code to parse it:
JsonNode json = new ObjectMapper().readTree(jsonString);
JsonNode registration_fields = json.get("registration");
Iterator<String> fieldNames = registration_fields.getFieldNames();
while(fieldNames.hasNext()){
String fieldName = fieldNames.next();
String fieldValue = registration_fields.get(fieldName).asText();
System.out.println(fieldName+" : "+fieldValue);
}
This works fine and it print all the values except for location which is kind of another level of nesting. I tried the same trick as above code to pass json.get("location") but that does not work. Please suggest how to make it work for location.

You need to detect when you are dealing with a (nested) Object using JsonNode#isObject:
public static void printAll(JsonNode node) {
Iterator<String> fieldNames = node.getFieldNames();
while(fieldNames.hasNext()){
String fieldName = fieldNames.next();
JsonNode fieldValue = node.get(fieldName);
if (fieldValue.isObject()) {
System.out.println(fieldName + " :");
printAll(fieldValue);
} else {
String value = fieldValue.asText();
System.out.println(fieldName + " : " + value);
}
}
}
Thus, when you reach an object, such as location, you'll call the printAll recursively to print all its inner values.
org.codehaus.jackson.JsonNode json = new ObjectMapper().readTree(jsonString);
org.codehaus.jackson.JsonNode registration_fields = json.get("registration");
printAll(registration_fields);

Since location is nested within registration, you need to use:
registration_fields.get("location");
to get it. But isn't it already processed by the while-loop, why do you need to get it separately?

Related

Update Json value in json Array in Java

{
"page": {
"size": 2,
"number": 2
},
"places": [
{
"eventName": "XYZ",
"createdByUser": "xyz#xyz.com",
"modifiedDateTime": "2021-03-31T09:59:48.616Z",
"modifiedByUser": "xyz#xyz.com"
}
]}
I am trying to update the "eventName" field with new String. I tried with the following code, It updates the field but returns only four fields in the json array.
public String modifyJson() throws Exception{
String jsonString = PiplineJson.payload(PiplineJson.filePath());
System.out.println(jsonString);
JSONObject jobject = new JSONObject(jsonString);
String uu = jobject.getJSONArray("places")
.getJSONObject(0)
.put("eventName", randomString())
.toString();
System.out.println(uu);
return uu;
}
This is what the above code does.
{
"eventName": "ABCD",
"createdByUser": "xyz#xyz.com",
"modifiedDateTime": "2021-03-31T09:59:48.616Z",
"modifiedByUser": "xyz#xyz.com"
}
I am trying to get the complete json once it updates the eventName filed.
{
"page": {
"size": 2,
"number": 2
},
"places": [
{
"eventName": "ABCD",
"createdByUser": "xyz#xyz.com",
"modifiedDateTime": "2021-03-31T09:59:48.616Z",
"modifiedByUser": "xyz#xyz.com"
}
]}
The problem is the way that you are chaining the operations together. The problem is that you are calling toString() on the result of the put call. The put calls returns the inner JSONObject that it was called on. So you end up serializing the wrong object.
Changing this:
String uu = jobject.getJSONArray("places")
.getJSONObject(0)
.put("eventName", randomString())
.toString();
to
jobject.getJSONArray("places")
.getJSONObject(0)
.put("eventName", randomString());
String uu = jobject.toString();
should work.
That's because you are returning the first element you extracted from "places" array. You should return "jobject.toString()" instead.

Dynamic way to access JSON nested values in Java

I have this JSON object:
{
"maindrawer":
{
"enabled": true,
"actions":
[
{
"type": "Section",
"title": "Section 1"
},
{
"id": 1,
"type": "Primary",
"title": "Title 1",
"badge":
{
"enabled": false,
"value": 0,
"textColor": "#000000",
"badgeColor": "#ff0990"
},
"subActions":
[
{
"id": 1,
"type": "Primary",
"title": "Sub Title 1"
}
]
}
]
}
}
This is the code I'm using to access the badge -> textColor value:
public void loadJSONFromRaw(Context context, int id)
{
json = null;
try
{
//read and return json sting
InputStream is = context.getResources().openRawResource(id);
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
json = new String(buffer, "UTF-8");
//convert json to object
Type type = new TypeToken<Map<String, Object>>() {}.getType();
Map<String, Object> data = new Gson().fromJson(json, type);
//access maindrawer property
Map<String, Object> maindrawer = (Map<String, Object>)data.get("maindrawer");
//access actions list
List<Object> actions = (List<Object>)maindrawer.get("actions");
//return first item in the list
Map<String, Object> action = (Map<String, Object>) actions.get(1);
//return badge object
Map<String, String> badge = (Map<String, String>) action.get("badge");
//access badge -> textColor value
String textColor = badge.get("textColor");
}
catch (IOException e)
{
e.printStackTrace();
}
}
Is there a better/faster or more dynamic way to access JSON nested properties using java/android? I'm using Gson library for this task and don't mind to switch to any other solution to make it easier as this is too much of code to write just to access a single variable.
Ideally, I'm looking for something like:
String textColor = data.get("maindrawer").get("actions").get(1).get("badge").get("textColor");
Also I'm not very interested in using POJO for now.
Lastly, I'm still new to Java so I'm probably missing something here or maybe there are some limitations? anyways thanks for you help!!
Found what I need using JsonPath library. It looks like it does similar to what I need. Here's a sample code I found:
String textColor = JsonPath.parse(json).read("$.maindrawer.actions[1].badge.textColor");
Very clean and straightforward. Hopes this will save someone else's time as well.
Since you are accessing json file locally, it means you know its structure.
So instead of using -
Map<String, Object> data = new Gson().fromJson(json, type);
You can use something like this-
Map<String, MainDrawer> data = new Gson().fromJson(json, type);
where MainDrawer is a class with member variables - enabled, actions and array of another type.
That would make easier to fetch your values like using -
mainDrawer.isEnabled()
Here are two solutions without importing a new library.
Write a simple path parser:
String textColor = (String)parse(data, "maindrawer", "actions", 1, "badge", "textColor");
//...
static Object parse(Object root, Object... params) {
Object current = root;
for (Object p : params) {
if (p instanceof Number) {
current = ((List<?>)current).get(((Number)p).intValue());
} else {
current = ((Map<?,?>)current).get(p.toString());
}
}
return current;
}
Or parse and walk through Gson's JsonElement:
JsonElement root = new Gson().fromJson(json, JsonElement.class);
String textColor = root
.getAsJsonObject().get("maindrawer")
.getAsJsonObject().get("actions")
.getAsJsonArray().get(1)
.getAsJsonObject().get("badge")
.getAsJsonObject().get("textColor")
.getAsString();
You can also do this with BSON using a single line query. You have to cast the object to the type as you go down into Nested JSON objects.
//import java.util.ArrayList;
//import org.bson.Document;
Document root = Document.parse("{ \"maindrawer\" : { \"enabled\" : true, \"actions\" : [{ \"type\" : \"Section\", \"title\" : \"Section 1\" }, { \"id\" : 1, \"type\" : \"Primary\", \"title\" : \"Title 1\", \"badge\" : { \"enabled\" : false, \"value\" : 0, \"textColor\" : \"#000000\", \"badgeColor\" : \"#ff0990\" }, \"subActions\" : [{ \"id\" : 1, \"type\" : \"Primary\", \"title\" : \"Sub Title 1\" }] }] } }");
System.out.println(((String)((Document)((Document)((ArrayList)((Document)root.get("maindrawer")).get("actions")).get(1)).get("badge")).get("textColor")));

How to set nested JSON data to datatables?

I have a (nested) data structure containing objects and arrays. And trying to sent datatables but only one value displaying.
JSON data:
{
"data": [{
"name": "name1",
"value": "value1",
"list": [{
"sname": "sname1",
"svalue": "svalue1"
}, {
"sname": "sname2",
"svalue": "svalue2"
}]
}]
}
JSON data getting through URL by using Java.
jQuery code:
var pk = $("#pk").val();
console.log(pk);
url = "/register/search?id=" + pk;
console.log(url);
$('#largeTable').DataTable({
"ajax": url,
"bDestroy": true,
"columns": [{
"data": "name"
},
{
"data": "value"
},
{
"data": "list.1.sname"
},
{
"data": "list.1.svalue"
},
{
"data": null,
"defaultContent": editview
}
]
});
Here it is possible to display either first or second list values by using list.1 or list.0
But I want two values at a time.
If you used render or mRender you can do what you want with the object. For example you can traverse the array like in this example.
$('#largeTable').DataTable({
"columnDefs": [
{"targets": [0], "title":"name", "data":"name"},
{"targets": [1], "title":"value", "data":"value"},
{"targets": [2], "title":"list", "data":"list", "type":"html"
"render":function(data){
var listArray = data;
var listHtml = "";
for(var i=0;i<listArray.length;i++) {
listHtml += listArray[i].sname + " " + listArray[i].svalue + "<br>";
}
return listHtml;
},
}]
});
$.ajax({
"type":"GET",
"url":url,
"success":function(data,status) {
var jsonData = $.parseJSON(data);
$('#largeTable').dataTable().fnAddData(jsonData);
}
Your list in json data structure is an array. So, you should use
list.forEach(function(element) {
//console.log(element);
});
You could create an object and build JSON dynamically and set it to "columns" array.
Here is an example:
// make an empty object
var myObject = {};
// set the "list1" property to an array of strings
myObject.list1 = ['1', '2'];
// you can also access properties by string
myObject['list2'] = [];
// accessing arrays is the same, but the keys are numbers
myObject.list2[0] = 'a';
myObject['list2'][1] = 'b';
myObject.list3 = [];
// instead of placing properties at specific indices, you
// can push them on to the end
myObject.list3.push({});
// or unshift them on to the beginning
myObject.list3.unshift({});
myObject.list3[0]['key1'] = 'value1';
myObject.list3[1]['key2'] = 'value2';
myObject.not_a_list = '11';

JSON Parsing Nested Array Objects

Using Simple-JSON on the following JSON formatted file, I'm having a lot of trouble understanding how to access the objects within the array under "name".
JSON File:
[
{
"name":{
"firstName": "Developer",
"lastName": "D"
},
"id": 00,
"permissionLevel": 3,
"password": 12345
},
{
"name":{
"firstName": "Bob",
"lastName": "Smith"
},
"id": 01,
"permissionLevel": 2,
"password": 23456
}
]
I'm able to obtain the information for all of the other contents because they're not located in a nested array; However, when I attempt to retrieve the objects under "name", all that is output is the String found in the JSON file.
Current code:
String[] searchData = {
"name",
"firstName",
"lastName",
"id",
"permissionLevel",
"password"
};
jsonArray = (JSONArray)new JSONParser().parse(s);
for(int i = 0; i < jsonArray.size(); i++){
JSONObject jo = (JSONObject)jsonArray.get(i);
for(int j = 0; j < searchData.length; j++){
System.out.println(
searchData[j] + ": " + jo.get(searchData[j]));
}
}
Output:
name: [{"firstName":"Developer","lastName":"D"}]
firstName: null
lastName: null
id: 0
permissionLevel: 3
password: 12345
name: [{"firstName":"Bob","lastName":"Smith"}]
firstName: null
lastName: null
id: 1
permissionLevel: 2
password: 23456
As you can see, "name" outputs a String from the JSON file, and not each individual value.
In the end, I need to write a universal code that can accept new "searchData" tags for each file that's input.
Might someone be able to direct me how to obtain objects held
within nested arrays?
Or perhaps I need to use a different Library? If so, which one is the most efficient for Java? I'm not programming for Android, and I continue to find Library suggestions for Android, constantly.
My apologies if this post is a dupe, but no other posts are aiding me.
You should get your firstname and lastname, like:
jo.get("name").get("firstname");
jo.get("name").get("lastname");
To get the objects held within nested arrays/objects, you will have to write a recursive method and flatten the structure into a map. Below example shows the same:
public static void main(String args[]) throws ParseException {
Object object = new JSONParser().parse("[ { \"name\":{ \"firstName\": \"Developer\", \"lastName\": \"D\" }, \"id\": 00, \"permissionLevel\": 3, \"password\": 12345 }, { \"name\":{ \"firstName\": \"Bob\", \"lastName\": \"Smith\" }, \"id\":01, \"permissionLevel\": 2, \"password\": 23456 }]");
Map<String, Object> pairs = new HashMap<>();
addValues(object, pairs);
System.out.println(pairs);
}
public static void addValues(Object object, Map<String, Object> pairs){
if(object instanceof JSONObject){
JSONObject jsonObject = (JSONObject) object;
for(String key : jsonObject.keySet()){
if(jsonObject.get(key) instanceof JSONObject || jsonObject.get(key) instanceof JSONArray){
addValues(jsonObject.get(key), pairs);
}else{
pairs.put(key, jsonObject.get(key));
}
}
}else if(object instanceof JSONArray){
JSONArray jsonArray = (JSONArray)object;
for(Object element : jsonArray){
addValues(element, pairs);
}
}
}
You can tweak this method to have keys like name.firstname or name.lastname depending on requirements.
I understand that you want the searchData tags to be taken into consideration while parsing the JSON. I would suggest using Google Gson for this case.
You can write a POJO which return the ArrayList<User> for your JSON.
Refer this article on how use Google Gson

Issue In extracting desired data from the Json Response

My Json response looks like this:
{
"oAuthClientResponse": {
"grantTypes": [
"client_credentials",
"urn:ietf:params:oauth:grant-type:jwt-bearer"
],
"appId": "0e0da052-baab-4e86-a826-edfcaadbd93b",
"certAlias": "tenant_269869150664042.st2Oauth.st2Oauth_svc_269869150693042_st2_client_OAUTHCLIENT.cert",
"clientCertificate": "MIIC",
"paramList": null,
"audiences": [
"http://svc.com/EndPoint/st2/CommonApi::RW",
"http://svc.com/EndPoint/st2/CommonApi::RO"
],
"isDisabled": "false",
"clientMetadata": {
"isTenantManaged": "false",
"isTrusted": "true"
},
"activityData": {
"createdOn": "08/10/2015 02:15:55"
},
"tenant": "tenant_269869150664042",
"description": "st2Oauth_svc_269869150693042_st2_client_OAUTHCLIENT",
"name": "st2Oauth_svc_269869150693042_st2_client_OAUTHCLIENT",
"appSecret": "EghTRToAFJUWHrsnXlK5",
"clientType": "CONFIDENTIAL_CLIENT"
}
}
I want to read the value of audiences.
String value = jObject.getJSONObject("oAuthClientResponse").getString(
"audiences");
In value I am getting :
"audiences": [
"http://svc.com/EndPoint/st2/CommonApi::RW",
"http://svc.com/EndPoint/st2/CommonApi::RO"
]
Now I am not able to extract the value of the audiences.i.e.
http://svc.com/EndPoint/st2/CommonApi::RW and
http://svc.com/EndPoint/st2/CommonApi::RO
Kindly suggest.
Use getJSONArray() instead of getString()
JSONArray audiences = jObject.getJSONObject("oAuthClientResponse")
.getJSONArray("audiences");
Then you can retrieve the individual values using indices
System.out.println(audiences.getString(0)); // http://svc.com/EndPoint/st2/CommonApi::RW
System.out.println(audiences.getString(1)); // http://svc.com/EndPoint/st2/CommonApi::RO
String value = jObject.getJSONObject("oAuthClientResponse").getString(
"audiences");
value = value.subString(value.indexOf('['))
value = value.replace("[","");
value = value.replace("]","");
value = value.replace("\"","");
StringTokenizer stringTokenizer = new StringTokenizer(
actualOutput, ",");
while (stringTokenizer.hasMoreElements()) {
String value = (String) lineTokenizer.nextElement();
System.out.println(value)
}

Categories