Convert JSON string to plain key value pair for logging - java

I have a JSON string, where consist of structure something like below, basically I have a chain of VO's and each VO will have list of VO's and Map of VO's as well.
sample:
"MessageHeader": {
"type": "new",
"id": 10,
"add_record": "true",
},
"MessageBody": {
"dob_required": false,
"dept_name": "Purchase",
"group": {
"main_group": "main group",
"sub_group": "sub group"
},
"family_info": {
"person1": {
"name": "HisName",
"gender": "male",
"age": "31",
"office_info_present": {
"office_name": "present office",
"office_address": "some address"
"some_other_vo":{
},
},
"office_info_previous": {
"office_name": "old office",
"office_address": "some address"
},
},
"person2": {
"name": "HerName",
"gender": "Female",
"age": "25",
}
},
"active":true
}
I want to print each and every attribute name and its value in key value pair. I don't want to print the VO name, rather just the end attributes (leaf level attributes)
like below string:
type=new id=10 add_record=true dob_required=false dept_name=purchase main_group="main group" sub_group="sub group" name=HisName gender=male age=31 .... name=HerName gender=Female age=25
How this can be done? I would prefer if it can be done using jackson. Otherwise also fine.

The easiest way is probably by using Jackson's Tree Model, traversing it. Something like:
JsonNode root = mapper.readValueAsTree(jsonInput);
Map<String,String> flat = new HashMap<String,String>();
traverse(root, flat);
public void traverse(JsonNode node, Map<String,String> result)
{
Iterator<Map.Entry<String,JsonNode>> it = node.fields();
while (it.hasNext()) {
Map.Entry<String,JsonNode> entry = it.next();
JsonNode n = entry.getValue();
if (n.isObject()) { // if JSON object, traverse recursively
traverse(n);
} else { // if not, just add as String
result.put(entry.getKey(), n.asText());
}
}
}
and you'll get a Map that you can print.

you can use this link for creating POGO class for your response. It will automatically generate class for your response.
Use google GSON library to parse your response.

Yes jackson can be used to parse. but its not straight forward.
There are few implementations similar to JAXB for XML. But I never tested them
Here is the rough code snippet.
JSONParser parser = new JSONParser();
try {
JSONObject jsonObject = (JSONObject) parser.parse(new FileReader("c:\\sample.json"));
String name = (String) jsonObject.get("name");
long age = (Long) jsonObject.get("age");
JSONArray msg = (JSONArray) jsonObject.get("messages");
System.out.println("Name:"+name);
System.out.println("Age:"+age);
System.out.println("Messages:");
Iterator<String> iterator = msg.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}

Related

How to flatten JSON using Gson

I need to flatten a JSON strings(nested) using Gson ,
Given:
{
"name": "Terry",
"addr": {
"city": "NY",
"postCode": 123
},
"friends": ["John", "Paul"],
"nestedObject": { "a": { "b": { "c": {"d": "nested property" } } } }
}
Expected:
{
"name" :"Terry",
"addr.city": "NY",
"addr.postCode" : 123,
"friends.0": "John",
"friends.1": "Paul",
"nestedObject.a.b.c.d": "nested property"
}
or
{
"name" :"Terry",
"addr.city": "NY",
"addr.postCode" : 123,
"friends[0]": "John"
"friends[1]": "Paul"
"nestedObject.a.b.c.d": "nested property"
}
Really new to Java and need guidance how to build it up ,
My starting point :
1.Parse the Json using JsonParser as TreeModel
https://www.tutorialspoint.com/gson/gson_tree_model.htm
just found that JsonParser is deprecated :(
https://javadoc.io/doc/com.google.code.gson/gson/latest/com.google.gson/com/google/gson/JsonParser.html
is there alternative ?
2.Recursive function to loop through the Json elements and check
if element is list/dict - case yes , recursive call with all child ,
case else - append current key and val to some map
real pseudo code:
public class Test{
public static void main(String[] args) {
String jsonString = "{\"brand\" : \"Toyota\", \"doors\" : 5}";
JsonObject jsonObject = JsonParser.parseString(jsonString).getAsJsonObject();
// Iterate through main key and call FlatJson for each one
// append result to a map
//print result
FlatJson - for given element ,
extract all child key
public String FlatJson( JsonElement jsonElement) {
// If input is an array, iterate through each element
if (jsonElement.isJsonArray()) {
for (JsonElement jsonElement1 : jsonElement.getAsJsonArray()) {
// Extract Key Value and return
}
} else {
// If input is object, iterate through the keys
if (jsonElement.isJsonObject()) {
Set<Map.Entry<String, JsonElement>> entrySet = jsonElement
.getAsJsonObject().entrySet();
for (Map.Entry<String, JsonElement> entry : entrySet) {
// Extract Key Value and return
}
}
}
// If input is element, check whether it corresponds to the key
else {
// return sonElement.toString() (as
}
}
}
}

Access only the First Object from a JSON Array

This is my json from the code below:
"ict":[
{
"module1":{
"1":[
"OS",
"Operating system"
],
"2":[
"CA",
"Computer Application"
],
"3":[
"CM",
"Computational Mathematics"
],
"4":[
"CA",
"Computer Application"
],
"5":[
"Programming",
"Structured Programming"
]
},
I want to access this part
"1":["OS","Operating system"]
but get the string "OS" without fetching the whole string.
When I run my java code which is this:
private void addItemsFromJSON() {
try {
JSONObject jsonObject = new JSONObject(readJSONDataFromFile());
JSONArray coursea = jsonObject.getJSONArray("ict");
for (int i = 0; i < coursea.length(); i++) {
JSONObject cc = coursea.getJSONObject(i);
JSONObject contact = cc.getJSONObject("module1");
courses.add(new course(contact.getString("1"),"",String.valueOf(content.get(ran.nextInt(content.size())))));
}
} catch (JSONException | IOException e) {
Log.d(TAG, "addItemsFromJSON: 777", e);
}
}
The output that I get is ["OS", "Operating system"]
How can I retrieve only the first object from a json key array with multiple values?
The data at "1" refers to another JSONArray, so to get the first item in the array you would do something like this:
JSONArray array = contact.getJSONArray("1");
array.getString(0);
In JSON objects are denoted using {} and arrays with []. If you're trying to access a specific value in your JSON object then it's really just a case of following the path to it, through the arrays and objects.

Multidimentional JSON to CSV , non-nested CSV convertion working in JAVA

I have a JSON file which I need to flat and create a CSV from it. I was able to convert to CSV (I have a "users" wrapper) but inside "users" there is another wrapper named "identifiers", I want to iterate them as well and create a field for them.
I have a JSON file which looks like this :
{
"users": [
{
"displayName": "Sharad Dutta",
"givenName": "",
"surname": "",
"extension_user_type": "user",
"identities": [
{
"signInType": "emailAddress",
"issuerAssignedId": "kkr007#gmail.com"
}
],
"extension_timezone": "VET",
"extension_locale": "en-GB",
"extension_tenant": "EG12345"
},
{
"displayName": "Wayne Rooney",
"givenName": "Wayne",
"surname": "Rooney",
"extension_user_type": "user",
"identities": [
{
"signInType": "userName",
"issuerAssignedId": "kkr007"
}
],
"extension_timezone": "VET",
"extension_locale": "en-GB",
"extension_tenant": "EG12345"
}
]
}
I am trying to convert the JSON to CSV and this is what I was able to do :
Below is the code : As you can see, my JSON is wrapped inside a "users" type wrapper and in the JSON i have one more wrapper "identities", with the code that I did, I am able to iterate but the "identites" is coming out as JSON blob, I want something like this in place of identites
issuerType issuerAssignedId
bla bla bla bla bla bla
and not a JSON nested blol for identites.
public static void main(String[] args) throws JSONException {
String userJsonFile = "C:\\Users\\Administrator\\Desktop\\jsonRes\\json_format_user_data_input_file.json";
try {
userJsonAsString = readFileAsAString(userJsonFile);
} catch (Exception e1) {
e1.printStackTrace();
}
JSONObject output;
try {
output = new JSONObject(userJsonAsString);
JSONArray docs = output.getJSONArray("users");
File file = new File("C:\\Users\\Administrator\\Desktop\\jsonRes\\EmpDetails.csv");
String csv = CDL.toString(docs);
FileUtils.writeStringToFile(file, csv);
System.out.println("Data has been Sucessfully Writeen to " + file);
System.out.println(csv);
} catch (Exception e) {
e.printStackTrace();
}
}
private static String readFileAsAString(String inputJsonFile) throws Exception {
return new String(Files.readAllBytes(Paths.get(inputJsonFile)));
}
Welcome to SO!
As you rightly said, "identities" is a nested JSON Array inside each element of the "users" array. So, when you flatten into a more-or-less relational format (here CSV), you would typically need to repeat the rest of the info for each element of the "identitites" array.
Now, whichever JSON parsing library you are using (JSONObject in you snippet, I am assuming comes from org.json jar?), you would need to iterate through the JSONArray docs and for each element call the getJSONArray("identities").
Since it is a nested array, you would need two loops to handle this scenario.
outer loop for the "users" array and a nested loop for the "identities" on each element of the "users" array.
Please use the below snippet as a reference only. Have written according to your code snippet. Please use standard variable naming and practices. This is just to show you the logic
String userJsonAsString="";
StringBuilder sBuild = new StringBuilder();
StringBuilder sBuild2 = new StringBuilder();
try {
userJsonAsString = readFileAsAString(userJsonFile);
} catch (Exception e1) {
e1.printStackTrace();
}
JSONObject output;
try {
output = new JSONObject(userJsonAsString);
JSONArray docs = output.getJSONArray("users");
Iterator<Object> iter = docs.iterator();
while(iter.hasNext()) {
JSONObject userEleObj = (JSONObject)iter.next();
JSONArray nestedIdArray = userEleObj.getJSONArray("identities");
Iterator<Object> nestIter = nestedIdArray.iterator();
while(nestIter.hasNext()) {
JSONObject identityEleObj = (JSONObject)nestIter.next();
identityEleObj.keySet().stream().forEach(key -> sBuild2.append(identityEleObj.get(key)+","));
userEleObj.keySet().stream().forEach(key -> {
if(StringUtils.equals(key, "identities")) {
sBuild.append(sBuild2.toString());
sBuild2.replace(0, sBuild2.length(), "");
} else {
sBuild.append(userEleObj.get(key)+",");
}
});
}
sBuild.replace(sBuild.lastIndexOf(","), sBuild.length(), "\n");
}
System.out.println(sBuild);
} catch (Exception e) {
e.printStackTrace();
}

How to get JSON data that contains JSON Object and array both

*I am already getting this JSON object from responce.body(). I want every data inside this separately in variable. I am using java.
{
"Classes":{
"Primary":{
"Classes":{
"1":{
"section":[
"a",
"b"
]
},
"2":{
"sections":[
"a",
"b"
]
}
}
}
}
}
*I know how to get the JSONObject but i dont know how can i get that array inside "section". even if i get that array with JSONArray then how to convert it to JSONObject? or String.
*Note that inside value of "section" array is dynamic, value inside that array is dynamic and can be multiiple from "a" to "z". Also JSONObject inside "Classes"(inside primary) is also dynamic. there can be dynamic and multiple "1","2"... and it is string, It is not necessary that there will be incremental numbers.
After 30 mins of war, I find out your answer just copy this code and paste where you want to use -
Here it is -
String json = "{
"Classes": {
"Primary": {
"Classes": {
"1": {
"section": [
"a",
"b"
]
},
"2": {
"sections": [
"a",
"b"
]
}
}
}
}
}";
try {
JSONObject jsonObject = new JSONObject(json);
Log.d("jsonObj", jsonObject.toString());
JSONObject classJsonObj = jsonObject.optJSONObject("Classes");
JSONObject primaryJsonObj = classJsonObj.optJSONObject("Primary");
JSONObject internalClassJsonObj = primaryJsonObj.optJSONObject("Classes");
if(internalClassJsonObj != null){
int i = 1;
JSONObject dynmaicInternalJsonObj = null;
while (true){
dynmaicInternalJsonObj = internalClassJsonObj.optJSONObject(i+"");
if(dynmaicInternalJsonObj != null){
JSONArray sectionJsonArr = dynmaicInternalJsonObj.optJSONArray("sections");
Log.d("SectionArr", sectionJsonArr.toString());
// Finally you got your section data here...
if(sectionJsonArr != null){
for(int j=0; j<sectionJsonArr.length(); j++){
System.out.println("Dynamic Sections Data is: - " + sectionJsonArr.opt(j));
}
System.out.println("\n\n");
}
}else{
break;
}
i++;
}
}
} catch (JSONException e) {
e.printStackTrace();
}
You've tagged this as java so I can only assume you want a solution for that language.
To use this data it needs to parsed, this means you are converting the data into a more usable type.
Click this to learn how to parse JSON in java
Assuming you need solution in java, use this to get a object classes for your json structure and then convert your json to java objects using libraries like GSON.
Example:
String json = "{\"city\":\"San Jose\", \"state\": \"CA\", \"country\":\"USA\"}";
Gson gson = new Gson();
Place place = gson.fromJson(json, Place.class);
If you are using ionic (typescript or javascript), you can use the below approach
var json = "{
"Classes": {
"Primary": {
"Classes": {
"1": {
"section": [
"a",
"b"
]
},
"2": {
"sections": [
"a",
"b"
]
}
}
}
}
}";
for(let item in json.Classes.Primary.Classes){
console.log(item.sections);
}
If you want to display the same data in frontend using html, use *ngFor
<div *ngFor="let item in json.Classes.Primary.Classes ">
<h5>{{item.sections}}</h5>
</div>
I hope it helps.

How to parse JSONObject with other JSONObjects inside it?

I have a question about getting jsonobjects out of a jsonobject.
This is what im getting back:
{
"data": {
"someid": {
"air_by_date": 0,
"cache": {
"banner": 1,
"poster": 1
},
"language": "en",
"network": "somenetwork",
"next_ep_airdate": "somedate",
"paused": 0,
"quality": "somequality",
"show_name": "somename",
"status": "Continuing",
"tvdbid": someid,
"tvrage_id": someid,
"tvrage_name": "Showname"
},
"someid": {
"air_by_date": 0,
"cache": {
"banner": 1,
"poster": 1
},
"language": "en",
"network": "somenetwork",
"next_ep_airdate": "",
"paused": 0,
"quality": "somequality",
"show_name": "somename",
"status": "Continuing",
"tvdbid": someid,
"tvrage_id": someid,
"tvrage_name": "somename"
},
But how am i supposed to create "ShowObjects" of them. I know how it works with JSONArrays but i have never done this kind of JSON before.
This is what i got untill now:
String json = download(url);
JSONObject result = new JSONObject(json);
JSONObject resultData = result.getJSONObject("data");
Copied from this answer:
Use the keys() iterator to iterate over all the properties, and call get() for each.
Iterator<String> iter = json.keys();
while (iter.hasNext()) {
String key = iter.next();
try {
Object value = json.get(key);
} catch (JSONException e) {
// Something went wrong!
}
}
Try using Jackson or Gson for these tasks.
With Jackson you would do something like this:
class Response() {
public String message;
public String result;
public Map<String, Object> data;
}
ObjectMapper mapper = new ObjectMapper()
Resonse respone = mapper.readValue(json, Response.class)
or use a custom deserializer to read those values out.
I will give you an example how to fetch the objects and vars in your "data" json:
lets say the second "someid" is : "123". We will fetch the second jsonObject now :
JSONObject secondJsonSomeId = resultData.getJsonObject("123");
Now we will fetch the "banner" ( int =1 ) of the jsonObject named "cache" located in our secondJsonSomeId :
int bannerInsecondJsonSomeId = secondJsonSomeId.getJsonObject("cache").getInt("banner");// bannerInsecondJsonSomeId == 1
the code is not compiled so there might be errors , ask if you have additional questions.

Categories

Resources