Converting plain JSON to tree format - json

I am trying to convert one json format into another as follows:-
I already have a Response POJO :-
class Response {
String id;
List<ResponseRowValues> values;
}
class ResponseRowValues {
String path;
List<String> values;
}
which is giving the json in this format :-
{
"id" : "12345",
"values" : [
{
"path": "Path A",
"values" : [ "val1", "val2"
]
},
{
"path": "Path A/Path B",
"values" : [ "val3", "val4"
]
},
{
"path": "Path A/Path B/Path C",
"values" : [ "val5", "val6"
]
}
]
}
I am trying to convert above json format into :-
{
"id" : "12345",
"data" : {
"record": [
{
"name" : "Path A",
"children" : [
{
"name": "Path B",
"children" : [
{
"name": "Path C",
"children" : [],
"values" : ["val5", "val6" ]
}
],
"values" : [
"val3", "val4"
]
}
],
"values" : [
"val1", "val2"
]
}
]
}
}
Trying to create a tree structure in java so that I can create json in above format.

Related

Filtering JSON objects with jq

I have a JSON file which contains unneeded values. I want to filter them by only selecting those I need, or deleting those I don't need. For example, I have this JSON file:
{
{ "id" : "1",
"key1" : "val1",
"key2" : "val2",
"name" : "someone",
"age" : 39,
},
{ "id" : "1234",
"key1" : "val1",
"key2" : "val2",
"name" : "someone",
"age" : 39
},
{ "id" : "4567",
"key1" : "val1",
"key2" : "val2",
"name" : "someone",
"age" : 60
}
}
My aim is to get the following JSON, by deleting all key1 and key2 items recursively using a jq command:
{
{ "id" : "1",
"name" : "someone",
"age" : 39,
},
{ "id" : "1234",
"name" : "someone",
"age" : 39
},
{ "id" : "4567",
"name" : "someone",
"age" : 60
}
}
Thank you.
If the input is supposed to be an array of objects (then format it as [{…},{…},{…}]), you can use map to apply filters or a new formatting onto each element of the array.
Construct what you need (Demo):
jq 'map({id,name,age})'
Or remove what you don't need (Demo):
jq 'map(del(.key1,.key2))'
Both produce:
[
{
"id": "1",
"name": "someone",
"age": 39
},
{
"id": "1234",
"name": "someone",
"age": 39
},
{
"id": "4567",
"name": "someone",
"age": 60
}
]

Transform nested array to top level array JOLT

Is it possible to transform a input JSON
{
"root": {
"lang" : "fr-FR",
"ttp" : "ttp1",
"net" : "wifi",
"gps" : [
{"gpslon" : "1", "gpslat" : "4"},
{"gpslon" : "2", "gpslat" : "5"},
{"gpslon" : "3", "gpslat" : "6"}
]
}
}
to another JSON file using JOLT transformation?
{
[
{
"lang" : "fr-FR",
"ttp" : "ttp1",
"net" : "wifi",
"gpslon" : "1",
"gpslat" : "4"
},
{
"lang" : "fr-FR",
"ttp" : "ttp1",
"net" : "wifi",
"gpslon" : "2",
"gpslat" : "5"
},
{
"lang" : "fr-FR",
"ttp" : "ttp1",
"net" : "wifi",
"gpslon" : "3",
"gpslat" : "6"
}
]
}
In other words i would like to copy "header" data (lang, ttp, net) to each array item gps.
Ok, i have found solution, may be not very efficient
[
{
"operation": "shift",
"spec": {
"root": {
"gps": {
"*": {
"#": "[&1]",
"#(2,lang)": "[&1].lang",
"#(2,ttp)": "[&1].ttp",
"#(2,net)": "[&1].net"
}
}
}
}
}
]

Mongodb Aggregate JSON array field for the matching field of other collection

I am new to mongodb , I have two collections like this :
1st collection name is A
{
"_id": "1234",
"versions": [{
"owner_id": ObjectId("100000"),
"versions": 1,
"type" : "info",
"items" : ["item1","item3","item7"]
},
{
"owner_id": ObjectId("100001"),
"versions": 2,
"type" : "bug",
"OS": "Ubuntu",
"Dependencies" : "Trim",
"items" : ["item1","item7"]
}
]}
2nd Collection name is B
{ "_id": ObjectId("100000"), "email": "abc#xyz.com" } { "_id": ObjectId("100001"), "email": "bbc#xyz.com"}
Expected output is :
{
"_id": "1234",
"versions":[{
"owner_id": "abc#xyz.com",
"versions": 1,
"type" : "info",
"items" : ["item1","item3","item7"]
},
{
"owner_id": "bbc#xyz.com",
"versions": 2,
"type" : "bug",
"OS": "Ubuntu",
"Dependencies" : "Trim",
"items" : ["item1","item7"]
}
] }
I used mongo $lookup but I am not getting required output
Please help.
Thank You!!!
You need to $unwind versions, $lookup with another collection on foreignField, $project to take the first element from the match array, $group to get back in original document format
collection a
> db.a.find()
{ "_id" : "1234", "versions" : [ { "owner_id" : "100000" }, { "owner_id" : "100001" }, { "owner_id" : "100001" } ] }
collection b
> db.b.find()
{ "_id" : "100000", "email" : "abc#xyz.com" }
{ "_id" : "100001", "email" : "bbc#xyz.com" }
aggregate pipeline
> db.a.aggregate(
[
{$unwind:"$versions"},
{$lookup : {from : "b", "localField":"versions.owner_id", "foreignField":"_id", as :"out"}},
{$project : {"_id":1, "versions.owner_id":{$arrayElemAt:["$out.email",0]}}},
{$group:{_id:"$_id", versions : {$push : "$versions"}}}
]
).pretty()
output
{
"_id" : "1234",
"versions" : [
{
"owner_id" : "abc#xyz.com"
},
{
"owner_id" : "bbc#xyz.com"
},
{
"owner_id" : "bbc#xyz.com"
}
]
}

Mongodb Aggregate : replace value of one collection with matching value of other collection

I am new to MongoDB, I have two collections like this :
1st collection name is a
db.a.find()
{
"_id": "1234",
"versions": [{
"owner_id": ObjectId("100000"),
"versions": 1,
"type" : "info",
"items" : ["item1","item3","item7"]
},
{
"owner_id": ObjectId("100001"),
"versions": 2,
"type" : "bug",
"OS": "Ubuntu",
"Dependencies" : "Trim",
"items" : ["item1","item7"]
}
]}
2nd Collection name is b
db.b.find()
{
"_id": ObjectId("100000"),
"email": "abc#xyz.com"
} {
"_id": ObjectId("100001"),
"email": "bbc#xyz.com"
}
Expected output is:
{
"_id": "1234",
"versions":[{
"owner_id": "abc#xyz.com",
"versions": 1,
"type" : "info",
"items" : ["item1","item3","item7"]
},
{
"owner_id": "bbc#xyz.com",
"versions": 2,
"type" : "bug",
"OS": "Ubuntu",
"Dependencies" : "Trim",
"items" : ["item1","item7"]
}
] }
Requirement: fields inside each document of versions are not fixed,
Example : versions[0] have 4 key-value pair and versions[1] have 6 key-value pair.
so I am looking a query which can replace owner_id with email keeping all other filed in output.
I tried :
db.a.aggregate(
[
{$unwind:"$versions"},
{$lookup : {from : "b", "localField":"versions.owner_id", "foreignField":"_id", as :"out"}},
{$project : {"_id":1, "versions.owner_id":{$arrayElemAt:["$out.email",0]}}},
{$group:{_id:"$_id", versions : {$push : "$versions"}}}
]
).pretty()
Please help.
Thank You!!!
Instead of $project pipeline stage use $addFields.
Example:
db.a.aggregate([
{ $unwind: "$versions" },
{
$lookup: {
from: "b",
localField: "versions.owner_id",
foreignField: "_id",
as: "out"
}
},
{
$addFields: {
"versions.owner_id": { $arrayElemAt: ["$out.email",0] }
}
},
{ $group: { _id: "$_id", versions: { $push: "$versions" } } }
]).pretty()

How to use `jq` to convert a json by combine some of the values?

Say I have a JSON:
{
"name":"my-project",
"projects" : [
{
"project": "core",
"configurations": [
{
"configuration": "compile",
"dependencies" : [
{
"organization": "a11",
"name" : "b11",
"version" : "1.1"
},
{
"organization": "a22",
"name" : "b22",
"version" : "2.2",
"dependencies" : [
{
"organization": "a33",
"name" : "b33",
"version" : "3.3"
}
]
}
]
}
]
}
]
}
How can I use jq to convert the JSON to:
{
"name":"my-project",
"projects" : [
{
"project": "core",
"configurations": [
{
"configuration": "compile",
"dependencies" : [
{
"dep" : "a11:b11:1.1"
},
{
"dep": "a22:b22:2.2",
"dependencies" : [
{
"dep": "a33:b33:3.3"
}
]
}
]
}
]
}
]
}
With a help of a function, you can do this recursively.
def update_dependencies:
{ dep: "\(.organization):\(.name):\(.version)" }
+
with_entries(select(.key == "dependencies") | .value |= map(update_dependencies))
;
.projects |= map(
.configurations |= map(
.dependencies |= map(update_dependencies)
)
)