Removing unused information from JSON - java

I am currently working with a SonicWall router. I am trying to get some information from it for a project. I am connecting to it via SSH and I have selected JSON as an output format to get all the information. The problem I have is the following. For simple commands the returned is pretty straightforward to parse but for more complex ones the returned JSON might not valid.
Here is a short example (these are NAT policies):
{
"success": true,
"cli": [
{ "command": [ { "token": "nat-policy" }, { "token": "inbound" }, { "token": "X1" }, { "token": "outbound" }, { "token": "X1" }, { "token": "destination" }, { "token": "name" }, { "token": "WAN Primary IP" }, { "token": "service" }, { "token": "name" }, { "token": "SNMP" } ] },
{ "submode": [
{ "command": [ { "token": "id" }, { "token": "0" } ] },
{ "command": [ { "token": "inbound" }, { "token": "X1" } ] },
{ "command": [ { "token": "outbound" }, { "token": "X1" } ] },
{ "command": [ { "token": "source" }, { "token": "any" } ] },
{ "command": [ { "token": "translated-source" }, { "token": "original" } ] },
{ "command": [ { "token": "destination" }, { "token": "name" }, { "token": "WAN Primary IP" } ] },
{ "command": [ { "token": "translated-destination" }, { "token": "original" } ] },
{ "command": [ { "token": "service" }, { "token": "name" }, { "token": "SNMP" } ] },
{ "command": [ { "token": "translated-service" }, { "token": "original" } ] },
{ "command": [ { "token": "enable" } ] },
{ "command": [ { "token": "comment" }, { "token": "Management NAT Policy" } ] },
{ "command": [ { "token": "exit" } ] }
] },
{ "command": [ { "token": "end" } ] }
] }
So as far as I can understand the return JSON contains a field "success" and a field "cli" which contains a field "command" that is a list of tokens and a field "submode" that is a list of commands that each hold a list of tokens.
I would like to remove the field "command" along with the list of token it holds so the result would be something like this:
{
"success": true,
"cli": [
{ "submode": [
{ "command": [ { "token": "id" }, { "token": "0" } ] },
{ "command": [ { "token": "inbound" }, { "token": "X1" } ] },
{ "command": [ { "token": "outbound" }, { "token": "X1" } ] },
{ "command": [ { "token": "source" }, { "token": "any" } ] },
{ "command": [ { "token": "translated-source" }, { "token": "original" } ] },
{ "command": [ { "token": "destination" }, { "token": "name" }, { "token": "WAN Primary IP" } ] },
{ "command": [ { "token": "translated-destination" }, { "token": "original" } ] },
{ "command": [ { "token": "service" }, { "token": "name" }, { "token": "SNMP" } ] },
{ "command": [ { "token": "translated-service" }, { "token": "original" } ] },
{ "command": [ { "token": "enable" } ] },
{ "command": [ { "token": "comment" }, { "token": "Management NAT Policy" } ] },
{ "command": [ { "token": "exit" } ] }
] }
] }
In essence I would only like to keep the "submode" field with the command list.
I am doing this in Java and cannot find a way to substring the returned JSON to get the expected result. Can anyone help with this?

You can use java jsonp:
JsonReader reader = Json.createReader(myJsonStream);
JsonObject obj = reader.readObject();
JsonBuilderFactory factory = Json.createBuilderFactory(null);
JsonObject myJson = factory.createObjectBuilder()
.add("success", obj.get("success"))
.add("cli", factory.createArrayBuilder()
.add(factory.createObjectBuilder()
.add("submode", obj.getJsonArray("cli").getJsonObject(1).get("submode")))).build();
FileOutputStream fs = new FileOutputStream("my_new_json_path");
JsonWriter wr = Json.createWriter(fs);
wr.writeObject(myJson);
wr.close();
Is bind to your json structure but it works!

Related

MongoDB : fields are excluded when invoke multiple lookup stages

db={
"dashboard": [
{
"_id": "dashboard1",
"name": "test",
"user": 1
}
],
"templatefolders": [
{
"dashboardId": "dashboard1",
"folderId": "folder123",
"name": "folder",
"region": "XXX"
}
],
"folders": [
{
"_id": "folder123"
}
],
"user": [
{
"_id": 1,
"name": "alaa"
}
],
}
this is my function:
db.dashboard.aggregate([
{
"$lookup": {
"from": "templatefolders",
"localField": "_id",
"foreignField": "dashboardId",
"as": "joinDashboard"
}
},
{
"$lookup": {
"from": "folders",
"localField": "joinDashboard.folderId",
"foreignField": "_id",
"as": "joinDashboard.joinFolder"
}
},
])
Result :
[
{
"_id": "dashboard1",
"joinDashboard": {
"joinFolder": [
{
"_id": "folder123"
}
]
},
"name": "test",
"user": 1
}
]
[![enter image description here][1]][1]
Why the fields name and region in collection templatefolders are excluded ?
I want to know why this behavior ? I don't like to use unwind because i have multiple collections with multiple refrence relation.
Your second $lookup, is overriding the joinDashboard key completely. Since you want joinFolder to be within joinDashboard, you can try nested lookups like this:
db.dashboard.aggregate([
{
$lookup: {
from: "templatefolders",
let: {
"boardId": "$_id"
},
pipeline: [
{
$match: {
$expr: {
$eq: [
"$dashboardId",
"$$boardId"
]
}
}
},
{
$lookup: {
from: "folders",
let: {
"folderId": "$folderId"
},
pipeline: [
{
$match: {
$expr: {
$eq: [
"$_id",
"$$folderId"
]
}
}
},
],
as: "joinFolder"
},
},
],
as: "joinDashboard"
}
}
])
MongoPlayground link.

How to form post request body where resource contained multi reference resources from Java to FHIR api

I have to send request body as org.hl7.fhir.r4.model.CoverageEligibilityRequest which is contained Patient, Practitioner, Organization as below. This API will return Bundle response. I am using Java and Generic client from Hapi Fire library. There is provision to pass search parameter but the here I am having multilevel hierarchy of resource and input is big than usual. Can any one help me to handle this request in FHIR API.
Request Body as below,
{
"resourceType": "CoverageEligibilityRequest",
"contained": [
{
"resourceType": "Patient",
"id": "1",
"name": [
{
"family": "abcFamily",
"given": [
"abcGiven"
]
}
],
"birthDate": "1962-08-06"
},
{
"resourceType": "Practitioner",
"id": "2",
"identifier": [
{
"type": {
"coding": [
{
"code": "NPI"
}
]
},
"value": "123456789"
}
],
"name": [
{
"family": "pqrFamily",
"given": [
"pqrGiven"
]
}
]
},
{
"resourceType": "Organization",
"id": "3",
"identifier": [
{
"value": "12345"
}
],
"name": ""
},
{
"resourceType": "Coverage",
"id": "3",
"status": "active",
"subscriberId": "",
"class": [
{
"type": {
"coding": [
{
"code": "group"
}
]
},
"value": ""
}
]
}
],
"extension": [
{
"url": "searchOption",
"valueString": "NameDateOfBirth"
}
],
"status": "active",
"purpose": [
"benefits"
],
"patient": {
"reference": "#1"
},
"provider": {
"reference": "#2"
},
"insurer": {
"reference": "#3"
}
}

How to find and update nested array element in an object on mongodb

I have a collection down below. I am trying to update an array element.
I am trying to update if lineItem _id value is 1 then go to spec list and update characteristicsValue from 900 to 50 if specName is "Model", as you can see, _id is also an array.
collection data:
{
"_id": "100",
"name": "Campaign",
"status": "Active",
"parts": {
"lineItem": [
{
"_id": [
{
"name": "A",
"value": "1"
}
],
"spec": [
{
"specName": "Brand",
"characteristicsValue": [
{
"value": "500"
}
]
},
{
"specName": "Model",
"characteristicsValue": [
{
"value": "900"
}
]
}
]
},
{
"_id": [
{
"name": "B",
"value": "2"
}
],
"spec": [
{
"specName": "Brand",
"characteristicsValue": [
{
"value": "300"
}
]
},
{
"specName": "Model",
"characteristicsValue": [
{
"value": "150"
}
]
}
]
},
{
"_id": [
{
"name": "C",
"value": "2"
}
]
}
]
}
}
related update doesnt work as I expected.
db.Collection.update({"parts.lineItem._id.value" : "1",
"parts.lineItem.spec.specName" : "Model" },{ $set: {
"parts.lineItem.spec.$.characteristicsValue" : "50" } })
EDIT:
Every _id has a spec array. so, we need to find _id and then go to spec under _id array, find the brand and update the value.
Try this way:
db.Collection.update(
{},
{ $set: { "parts.lineItem.$[outer].spec.$[inner].characteristicsValue" : "50" } },
{ multi: true, arrayFilters: [{"outer._id.value" : "1"}, {"inner.specName" : "Model"}]}
);

Groovy remove from map

The list below contains a collection of id's
List id_wanted = ['3894586', '2786438236', '895673985']
Given the list above, How do I remove elements from the JSON below that match with the id above List?
JSON:
{
"animals": [
{
"name": "lion",
"countries": [
{
"name": "kenya",
"facts": [
{
"features": [
"young male"
],
"age": "2y",
"id": "2837492"
}
]
},
{
"name": "tanzania",
"facts": [
{
"features": [
"cub"
],
"age": "0y",
"id": "3894586"
}
]
},
{
"name": "south africa",
"facts": [
{
"features": [
"adult lioness"
],
"age": "10y",
"id": "495684576"
},
{
"features": [
"young female"
],
"age": "4y",
"id": "2786438236"
}
]
}
]
},
{
"name": "giraffe",
"countries": [
{
"name": "zambia",
"facts": [
{
"features": [
"ex captivity"
],
"age": "20y",
"id": "343453509"
}
]
},
{
"name": "kenya",
"facts": [
{
"features": [
"male"
],
"age": "17y",
"id": "85604586"
}
]
},
{
"name": "uganda",
"facts": [
{
"features": [
"young female"
],
"age": "4y",
"id": "895673985"
},
{
"features": [
"none"
],
"age": "11y",
"id": "39860394758936764"
}
]
}
]
}
]
}
For example, the following block would be removed from the JSON above because id matches with the List id_wanted
{
"features": [
"young female"
],
"age": "4y",
"id": "2786438236"
}
Assuming your json is a String in a variable inputJson, it's probably easier to build a new Json document from the original with those values filtered out:
import groovy.json.*
def json = new JsonSlurper().parseText(inputJson)
List id_wanted = ['3894586', '2786438236', '895673985']
def result = new JsonBuilder([
animals: json.animals.collect {[
name: "$it.name",
countries: it.countries.collect { [
name: "$it.name",
facts: it.facts.findAll { !(it.id in id_wanted) }
]}
]}
]).toString()
You can parse your original json and modify the resulted data structure in-place using handy *. spread operator:
def json = slurper.parseText(original)
json.animals*.countries*.facts*.each { facts ->
facts.removeAll { fact -> fact.id in id_wanted }
}
def filtered = new JsonBuilder(json).toPrettyString()
println(filtered)
Output (with facts from id_wanted removed):
{
"animals": [
{
"name": "lion",
"countries": [
{
"name": "kenya",
"facts": [
{
"features": [
"young male"
],
"age": "2y",
"id": "2837492"
}
]
},
{
"name": "tanzania",
"facts": [
]
},
{
"name": "south africa",
"facts": [
{
"features": [
"adult lioness"
],
"age": "10y",
"id": "495684576"
}
]
}
]
},
{
"name": "giraffe",
"countries": [
{
"name": "zambia",
"facts": [
{
"features": [
"ex captivity"
],
"age": "20y",
"id": "343453509"
}
]
},
{
"name": "kenya",
"facts": [
{
"features": [
"male"
],
"age": "17y",
"id": "85604586"
}
]
},
{
"name": "uganda",
"facts": [
{
"features": [
"none"
],
"age": "11y",
"id": "39860394758936764"
}
]
}
]
}
]
}

Aggregation operation to modify the key of a property from a subdocument of documents

I have in mongo db a collection with documents like this:
{
"prop1": "val1",
"prop2": {
"prop21": {
"toBeChanged1_xyz": "val2",
"toBeChanged2_zyx": "val3",
},
"prop22": {
"whatever": "something"
}
}
}
Trying to create aggregation operation in Java Spring to remove from the keys of prop21's properties the substring after _. This if what I need to have:
{
"prop1": "val1",
"prop2": {
"prop21": {
"toBeChanged1": "val2",
"toBeChanged2": "val3",
},
"prop22": {
"whatever": "something"
}
}
}
Tried something like this:
List<AggregationOperation> operations = new ArrayList<AggregationOperation>();
operations.add( Aggregation.project( "code" ).and( "code" ).minus( "_"+"$entityType" ).as( "newId" ));
It didn't worked, of course. I have no idea how can it be done or can it be done easier in other ways.
You should update your structure to below.
{
"prop1": "val1",
"prop2": [
{
"prop": "prop21",
"value": [
{
"prop": "toBeChanged1_xyz",
"value": "val2"
},
{
"prop": "toBeChanged2_zyx",
"value": "val3"
}
]
},
{
"prop": "prop22",
"value": [
{
"prop": "whatever",
"value": "something"
}
]
}
]
}
You can try below query in 3.4. The query will iterate over property elements and locate prop2 and $split to modify the property name.
[
{
"$addFields": {
"prop2": {
"$map": {
"input": "$prop2",
"as": "prop_2",
"in": {
"prop": "$$prop_2.prop",
"value": {
"$cond": [
{
"$eq": [
"$$prop_2.prop",
"prop21"
]
},
{
"$map": {
"input": "$$prop_2.value",
"as": "prop_21",
"in": {
"prop": {
"$arrayElemAt": [
{
"$split": [
"$$prop_21.prop",
"_"
]
},
0
]
},
"value": "$$prop_21.value"
}
}
},
"$$prop_2.value"
]
}
}
}
}
}
}
]
You can use the below query if you cant modify the structure from 3.4.4 version.
The query uses $arrayToObject and $objectToArray operator to modify the documents to above structure with same logic to modify the property name.
[
{
"$addFields": {
"prop2": {
"$arrayToObject": {
"$map": {
"input": {
"$objectToArray": "$prop2"
},
"as": "prop_2",
"in": {
"k": "$$prop_2.k",
"v": {
"$cond": [
{
"$eq": [
"$$prop_2.k",
"prop21"
]
},
{
"$arrayToObject": {
"$map": {
"input": {
"$objectToArray": "$$prop_2.v"
},
"as": "prop_21",
"in": {
"k": {
"$arrayElemAt": [
{
"$split": [
"$$prop_21.k",
"_"
]
},
0
]
},
"v": "$$prop_21.v"
}
}
}
},
"$$prop_2.v"
]
}
}
}
}
}
}
}
]

Categories