How to traverse a JSON file? - java

The JSON I have is mentioned below :-
{ head: {
link: [],
vars: [
"CompanyName",
"Company_Name",
"Foundation_URI",
"Foundation_Name",
"Latitude",
"Longitude"
] }, results: {
distinct: false,
ordered: true,
bindings: [
{
CompanyName: {
type: "uri",
value: "http://dbpedia.org/resource/United_Christian_Broadcasters"
},
Company_Name: {
type: "literal",
xml:lang: "en",
value: "United Christian Broadcasters"
},
Foundation_URI: {
type: "uri",
value: "http://dbpedia.org/resource/Christchurch"
},
Foundation_Name: {
type: "literal",
xml:lang: "en",
value: "Christchurch"
},
Latitude: {
type: "typed-literal",
datatype: "http://www.w3.org/2001/XMLSchema#float",
value: "-43.52999877929688"
},
Longitude: {
type: "typed-literal",
datatype: "http://www.w3.org/2001/XMLSchema#float",
value: "172.6202850341797"
}
},
{
CompanyName: {
type: "uri",
value: "http://dbpedia.org/resource/United_Christian_Broadcasters"
},
Company_Name: {
type: "literal",
xml:lang: "en",
value: "UCB Media"
},
Foundation_URI: {
type: "uri",
value: "http://dbpedia.org/resource/Christchurch"
},
Foundation_Name: {
type: "literal",
xml:lang: "en",
value: "Christchurch"
},
Latitude: {
type: "typed-literal",
datatype: "http://www.w3.org/2001/XMLSchema#float",
value: "-43.52999877929688"
},
Longitude: {
type: "typed-literal",
datatype: "http://www.w3.org/2001/XMLSchema#float",
value: "172.6202850341797"
}
},
{
CompanyName: {
type: "uri",
value: "http://dbpedia.org/resource/Kathmandu_%28company%29"
},
Company_Name: {
type: "literal",
xml:lang: "en",
value: "Kathmandu"
},
Foundation_URI: {
type: "uri",
value: "http://dbpedia.org/resource/Christchurch"
},
Foundation_Name: {
type: "literal",
xml:lang: "en",
value: "Christchurch"
},
Latitude: {
type: "typed-literal",
datatype: "http://www.w3.org/2001/XMLSchema#float",
value: "-43.52999877929688"
},
Longitude: {
type: "typed-literal",
datatype: "http://www.w3.org/2001/XMLSchema#float",
value: "172.6202850341797"
}
}
] } }
I want to know that how can I traverse this JSON to get the values of the appropriate variables as mentioned in the JSON file. I would like to know this with respect to JavaScript as well as Java. Please let me know how to traverse this JSON so as to get data easily.

This is not a JSON string but luckily a YAML standrd format.
You can use YAML library to transverse your jSON-like string

Here is a rather simple tree traversal routine:
function traverse(o) {
if( o instanceof Object ) {
for( key in o ) {
traverse(o[key]);
}
}
else if( o instanceof Array ) {
for( value in o ) {
traverse(value);
}
}
else {
console.log(o);
}
}
var q = { name : 'me', data : [ { a: 'a1', b: 'b1' }, { a: 'a2', b: 'b2'} ] };
traverse(q);
However, I think this is not quite what you're looking for. Please clarify and I will update my answer accordingly.

Following is a simple traversing of JSON object, this should help you undersatnd your JSON object normal traversing. Check the https://github.com/substack/js-traverse link for a detailed tutorial for complex traversing of any javascript object
<script language="javascript">
var emp = {"details" : [
{
"Name" : "Nitin1",
"Salary" : 10000,
"DOJ" : "16th Sept 2010"
}
,
{"Name" : "Abhijit2",
"Salary" : 5000,
"DOJ" : "15th Sept 2010"}
,
{"Name" : "Nilesh",
"Salary" : 50000,
"DOJ" : "10th Sept 2010"}
]
};
document.writeln("<table border='1'><tr><td>Name</td><td>Salary</td><td>DOJ</td></tr>");
var i=0;
for(i=0;i<emp.details.length; i++)
{
document.writeln("<tr><td>" + emp.details[i].Name + "</td>");
document.writeln("<td>" + emp.details[i].Salary +"</td>");
document.writeln("<td>" + emp.details[i].DOJ +"</td></tr>");
}
document.writeln("</table>");
</script>

If you only want to retrieve particular values - you do not need to traverse the entire JSON file.
This can be done in Javascript as follows:
Declared JSON variable:
var myJSONObject = {"bindings": [
{"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"},
{"ircEvent": "PRIVMSG", "method": "deleteURI", "regex": "^delete.*"},
{"ircEvent": "PRIVMSG", "method": "randomURI", "regex": "^random.*"}
]
};
Fetch a particular value:
myJSONObject.bindings[0].method // "newURI"
For a full reference you can go here.
I do not use Java myself, but XML.java (documentation available here) allows you to convert the JSON into XML. Parsing an XML is easy - you will find plenty of tutorials on it for Java such as:
http://www.seas.gwu.edu/~simhaweb/java/xml/xml.html
Cheers!

Related

Need JOLT spec for array input JSON

I am working on transforming a complex json using JOLT.
Input JSON:
{ "data":
[
{
"fieldname": "Name",
"fieldvalue": [ "John Doe" ]
},
{ "fieldname": "Title",
"fieldvalue": [ "Manager" ]
},
{ "fieldname": "Company",
"fieldvalue": [ "Walmart" ]
}
] }
Expected Output:
{
"finalPayload":{
"PI":{
"EmpName":"John Doe",
"EmpRole":"Manager"
},
"Company":"Walmart"
}
}
I am unable to understand how to access and assign "fieldvalue" in output based on "fieldname". Please help me with the JOLT spec.
Note: The order of name, title and company in input JSON will be jumbled and random meaning its not mandatory that under "data" array first object will be related to "Name" only.
Hi hope this helps you in resolving your issue.
You can have condition in Jolt too, by going inside the variable and checking the fieldname.
[
{
"operation": "shift",
"spec": {
"data": {
"*": {
"fieldname": {
"Name": {
"#(2,fieldvalue)": "finalPayload.PI.EmpName"
},
"Title": {
"#(2,fieldvalue)": "finalPayload.PI.EmpRole"
},
"Company": {
"#(2,fieldvalue)": "finalPayload.Company"
}
}
}
}
}
},
{
"operation": "cardinality",
"spec": {
"finalPayload": {
"PI": {
"EmpName": "ONE",
"EmpRole": "ONE"
},
"Company": "ONE"
}
}
}
]
May I introduce an alternative library to solve the issue.
https://github.com/octomix/josson
implementation 'com.octomix.josson:josson:1.3.21'
-------------------------------------------------
Josson josson = Josson.fromJsonString(
"{\"data\":[{\"fieldname\":\"Name\",\"fieldvalue\":[\"JohnDoe\"]},{\"fieldname\":\"Title\",\"fieldvalue\":[\"Manager\"]},{\"fieldname\":\"Company\",\"fieldvalue\":[\"Walmart\"]}]}");
JsonNode node = josson.getNode(
"map(" +
" finalPayload: map(" +
" PI: map(" +
" EmpName: data[fieldname='Name'].fieldvalue[0]," +
" EmpRole: data[fieldname='Title'].fieldvalue[0]" +
" )," +
" Company: data[fieldname='Company'].fieldvalue[0]" +
" )" +
")");
System.out.println(node.toPrettyString());
Output
{
"finalPayload" : {
"PI" : {
"EmpName" : "JohnDoe",
"EmpRole" : "Manager"
},
"Company" : "Walmart"
}
}

Java. MongoDB. Sort sub document after unwind

I have users, and skills into the user.
[
{
"_id": "5b91668a0f77e30c11574c88",
"full_name": "John Smith"
"skills": [
{
"_id": "61966603ceb6da478418aac0",
"name": "Java",
"active": true
},
{
"_id": "61966533ceb6da4092707441",
"name": "Scala",
"active": true
},
{
"_id": "619f9dce86b62c370e1c5fcc",
"name": "MongoDB",
"active": true
}
]
}
]
I need to get all user skills in A-Z order by name. I found many solutions, but they are all for MongoDB. I am trying to use the functions of the class com.mongodb.client.model.Agregate, but sorting doesn't work for me (returns in a different order, but it is not clear in what order.) and I do not understand why. Maybe I am do something wrong, or exist another implementation of my task?
var result = getCollection().aggregate(
asList(
match(eq("_id", userId)),
unwind("$skills"),
sort(ascending("skills.name")),
group(null, addToSet("skills", "$skills"))),
Document.class);
Alternatively, you can altogether avoid the $unwind, $sort and $group stages, and use the following aggregation $addFileds (or $project) stage to sort the array elements. This uses the $function aggregate expression (MongoDB v4.4).
Consider an input document:
{
skills: [ { name: "Java" }, { name: "Scala" }, { name: "Mongo" }, { name: "Groovy" } ]
}
The query:
db.collection.aggregate([
{
$addFields: {
skills: {
$function: {
body: function(input) {
const sorter = function(x1, x2) {
if (x1.name > x2.name) {
return 1;
}
else if (x2.name > x1.name) {
return -1;
}
else {
return 0;
};
};
input.sort(sorter);
return input;
},
args: [ "$skills" ],
lang: "js"
}
}
}
}
])
The output with sorted skills array (by name field):
skills: [ { name: "Groovy" }, { name: "Java" }, { name: "Mongo" }, { name: "Scala" } ]

Trying to get the name of the object whose collection array contains 'random'

I'm trying to get the names of the object whose collection array contains the word 'random'. Have tried various json path queries but couldn't get the right one.
{
"elements": [
{
"name": "My first element",
"language": "French",
"tags": ["Paris", "baguette", "Eiffel tower"]
},
{
"name": "randomOne",
"language": "Gibberish",
"tags": ["random", "plant, bag"]
},
{
"name": "bliep",
"language": "English",
"tags": ["lamp", "table, bed, oven"]
}
]}
Try this :
const jsonObj = {
"elements": [{
"name": "My first element",
"language": "French",
"tags": ["Paris", "baguette", "Eiffel tower"]
},
{
"name": "randomOne",
"language": "Gibberish",
"tags": ["random", "plant, bag"]
},
{
"name": "bliep",
"language": "English",
"tags": ["lamp", "table, bed, oven"]
}
]
};
let obj = jsonObj.elements.find((obj) => obj.tags.includes('random'));
console.log(obj.name); // randomOne
You can simply:
Loop through elements with Array.prototype.forEach()
Find instances containing "random" with Array.prototype.includes()
Add found names to result array with Array.prototype.push()
See below:
const jsondata = {
elements: [{
name: "My first element",
language: "French",
tags: ["Paris", "baguette", "Eiffel tower"]
},
{
name: "randomOne",
language: "Gibberish",
tags: ["random", "plant, bag"]
},
{
name: "bliep",
language: "English",
tags: ["lamp", "table, bed, oven"]
}
]
};
const result = [];
jsondata.elements.forEach(elem => {
if (elem.tags.includes("random")) {
result.push(elem.name);
}
});
console.log(result); // [ 'randomOne' ]
I have tried this question and able to get the names whose having 'random' in collection array.
$.elements[?(#.tags.indexOf('random') != -1)].name
Please update if it serves your purpose.

How to get values of keys of inside array in json array

This is the string that I get which I want to parse as json and get the values of "s", "o", "c" and "p" .
{
"head": {
"vars": [
"s",
"c",
"o",
"p"
]
},
"results": {
"bindings": [
{
"s": {
"type": "uri",
"value": "http://example.org/data/window"
},
"c": {
"type": "uri",
"value": "http://www.w3.org/ns/sosa/FeatureOfInterest"
},
"o": {
"type": "uri",
"value": "http://example.org/data/window104state"
},
"p": {
"type": "uri",
"value": "http://www.w3.org/ns/ssn/hasProperty"
}
},
{
"s": {
"type": "uri",
"value": "http://example.org/data/earth"
},
"c": {
"type": "uri",
"value": "http://www.w3.org/ns/sosa/FeatureOfInterest"
},
"o": {
"type": "uri",
"value": "http://example.org/data/VCAB-DP1-BP-40location"
},
"p": {
"type": "uri",
"value": "http://www.w3.org/ns/sosa/hasSample"
}
}
]
}
}
This is the code I have tried so far:
JsonParser jsonParser = new JsonParser();
JsonElement element = jsonParser.parse(str);
JsonObject obj = element.getAsJsonObject();
JsonObject results = obj.get("results").getAsJsonObject();
for(Map.Entry<String, JsonElement> entry : results.entrySet()) {
JsonArray array = entry.getValue().getAsJsonObject().getAsJsonArray("bindings");
for (JsonElement jsonElement : array) {
for (Map.Entry<String, JsonElement> entry1 : jsonElement.getAsJsonObject().entrySet()) {
System.out.println("Key = " + entry1.getKey() + " Value = " + entry1.getValue() );
}
}
What I want to get is the values of the inside array as such:
"s": "http://example.org/data/earth"
"c": "http://www.w3.org/ns/sosa/FeatureOfInterest"
etc.
Instead I get an error:
Exception in thread "main" java.lang.IllegalStateException: Not a JSON Object: [{"s":{"type":"uri","value":"http://example.org/data/window"},"c":{"type":"uri","value":"http://www.w3.org/ns/sosa/FeatureOfInterest"},"o":{"type":"uri","value":"http://example.org/data/window104state"},
(the whole string).
UPDATE
Thanks to #Deadpool I managed to get the values but now I need to get the "inner" values of the bindings meaning the "value" part of each binding(s,c,p and o). I need only this part and not the "type" part.
This is the result thanks to #Deadpool:
Key = s Value = {"type":"uri","value":"http://example.org/data/window"}
Key = c Value = {"type":"uri","value":"http://www.w3.org/ns/sosa/FeatureOfInterest"}
Key = p Value = {"type":"uri","value":"http://www.w3.org/ns/ssn/hasProperty"}
Key = o Value = {"type":"uri","value":"http://example.org/data/window104state"}
SOLUTION
OK for those interested I managed to get it this the statement that was needed:
System.out.println("Key = " + entry1.getKey() + " Value = " + entry1.getValue().getAsJsonObject().get("value"));
And this is the desired result:
Key = s Value = "http://example.org/data/earth"
Key = c Value = "http://www.w3.org/ns/sosa/FeatureOfInterest"
Key = o Value = "http://example.org/data/VCAB-DP1-BP-40location"
Key = p Value = "http://www.w3.org/ns/sosa/hasSample"
The problem is in this statement bindings is a JsonArray, get it as JsonArray directly
JsonArray array = entry.getValue().getAsJsonObject().getAsJsonArray("bindings");
Solution
for(Map.Entry<String, JsonElement> entry : results.entrySet()) {
JsonArray array = entry.getValue().getAsJsonArray();
for (JsonElement jsonElement : array) {
for (Map.Entry<String, JsonElement> entry1 : jsonElement.getAsJsonObject().entrySet()) {
System.out.println("Key = " + entry1.getKey() + " Value = " + entry1.getValue() );
}
}
You can use Declarative Stream Mapping (DSM) stream parsing library to easily capture data from XML or JSON
First of all, you must define the mapping between JSON data and your fields in yaml or JSON format.
Here are the mapping definitions:
result:
type: array
path: /results/bindings/(s|c|o|p) // regex
fields:
key:
path: type
value:
Java class that you want to deserialize:
public class KeyValue{
public String key;
public String value
}
Java Code to parse JSON:
DSM dsm=new DSMBuilder(new File("path/to/mapping.yaml")).create(KeyValue.class);
List<KeyValue> list= (List<KeyValue>)dsm.toObject(jsonData);
// write root object as json
dsm.getObjectMapper().writerWithDefaultPrettyPrinter().writeValue(System.out, list);
Here is output:
[ {
"key" : "uri",
"value" : "http://example.org/data/window"
}, {
"key" : "uri",
"value" : "http://www.w3.org/ns/sosa/FeatureOfInterest"
}, {
"key" : "uri",
"value" : "http://example.org/data/window104state"
}, {
"key" : "uri",
"value" : "http://www.w3.org/ns/ssn/hasProperty"
}, {
"key" : "uri",
"value" : "http://example.org/data/earth"
}, {
"key" : "uri",
"value" : "http://www.w3.org/ns/sosa/FeatureOfInterest"
}, {
"key" : "uri",
"value" : "http://example.org/data/VCAB-DP1-BP-40location"
}, {
"key" : "uri",
"value" : "http://www.w3.org/ns/sosa/hasSample"
} ]

JSON to JSON Transform of input sample using any existing java library/tools

Input:
{
"Student": {
"name" :"abc",
"id" : 588,
"class : "12"
}
}
Reqired Output:
{
"Student": {
"key" :"name",
"value":"abc",
"key" :"id",
"value":"588",
"key" :"class",
"value":"12"
}
}
Your output json invalid. Json object can not duplicate key .
You can use the library org.json and do something like this:
JSONObject jsonObject = new JSONObject(inputJson);
JSONObject outputJson = new JSONObject();
JSONArray array = new JSONArray();
for (Object key : jsonObject.keySet()) {
JSONObject item = new JSONObject();
String keyStr = (String)key;
Object keyvalue = jsonObj.get(keyStr);
item.put(keyStr, keyvalue);
array.put(item);
}
outputJson.put("Student", array);
System.out.println(json.toString());
Output :
{
"Student": [
{
"key": "name",
"value": "abc"
},
{
"key": "id",
"value": "588"
},
{
"key": "class",
"value": "12"
}
]
}
Similar to the other answer, the desired output JSON format is not valid.
The closest valid output would be
{
"Student" : [ {
"key" : "name",
"value" : "abc"
}, {
"key" : "id",
"value" : 588
}, {
"key" : "class",
"value" : "12"
} ]
}
This can be generated via Jolt with the following spec
[
{
"operation": "shift",
"spec": {
"Student": {
"name": {
"$": "Student[0].key",
"#": "Student[0].value"
},
"id": {
"$": "Student[1].key",
"#": "Student[1].value"
},
"class": {
"$": "Student[2].key",
"#": "Student[2].value"
}
}
}
}
]
This is easy to solve with JSLT if we assume the output is made valid JSON by making an array of key/value objects like the other respondents do.
The array function converts an object into an array of key/value objects exactly like you ask for, so the transform becomes:
{"Student" : array(.Student)}

Categories