I am pretty new to java and rest. I was trying to count elements from the item object using rest. If you check below Json then you will find 6 elements associated with the item object.
{
"response": {
"status": "active",
"timestamp": "2019-01-02 20:07:42"
},
"group": [
{
"best_option": "Offer",
"item": {
"F": [
{
"code": "228"
}
],
"E": [
{
"code": "228"
}
]
},
"review": {
"F": [
{
"code": "110"
},
{
"code": "212"
}
],
"E": [
{
"code": "110"
},
{
"code": "212"
}
]
}
},
{
"best_option": "Offer",
"item": {
"D": [
{
"code": "228"
}
],
"C": [
{
"code": "228"
}
]
},
"review": {
"D": [
{
"code": "110"
},
{
"code": "212"
}
],
"C": [
{
"code": "110"
},
{
"code": "212"
},
{
"code": ""
}
]
}
},
{
"best_option": "Offer",
"item": {
"A": [
{
"code": "228"
}
]
},
"review": {
"A": [
{
"code": "110"
},
{
"code": "212"
}
]
}
},
{
"best_option": "Offer",
"item": {
"B": [
{
"code": "228"
},
{
"code": "662"
}
]
},
"review": {
"B": [
{
"code": "110"
},
{
"code": "662"
}
]
}
}
]
}
I have tried jsonResponse.getBody().jsonPath().get() to count element from item object. I want to count number of elements present in the item object for e.g: A, B, C,D,E F . Can someone please help me to sort out my issue?
Iterate over "group" object, get "item" as JsonObject and get the size.
JsonObject jsonObject = (JsonObject)new JsonParser().parse(input);
JsonArray groupObject = jsonObject.getAsJsonArray("group");
int countItem=0;
for(int i=0;i<groupObject.size();i++) {
JsonObject items = ((JsonObject)groupObject.get(i)).getAsJsonObject("item");
countItem+=items.size();
}
Related
I have an array which I have to iterate and append object that is outside the list to each of the object inside list. It is not happening properly. Since offerings is an array if it has multiple objects to each object I need to have typeId of that object.
Request:
[
{
"offers": [
{
"type": {
"id": "5"
},
"offerings": [
{
"id": "10"
},
{
"id": "9"
}
]
},
{
"type": {
"id": "3"
},
"offerings": [
{
"id": "11"
}
]
},
{
"type": {
"id": "2"
},
"offerings": [
{
"id": "14"
},
{
"id": "16"
}
]
}
]
}
]
My spec:
[
{
"operation": "shift",
"spec": {
"*": {
"offers": {
"*": {
"type": {
"id": "[&4].[&2].typeId"
},
"offerings": {
"*": {
"id": "[&3].[&1].offerId"
}
}
}
}
}
}
},
{
"operation": "shift",
"spec": {
"*": {
"*": "[]"
}
}
}
]
Response now:
[
{
"typeId": "5",
"offerId": "10"
},
{
"offerId": "9",
"typeId": "3"
},
{
"typeId": "2"
},
{
"offerId": "11"
},
{
"offerId": "14"
},
{
"offerId": "16"
}
]
Expected:
[
{
"typeId": "5",
"offerId": "10"
},
{
"typeId": "5",
"offerId": "9"
},
{
"typeId": "3",
"offerId": "11"
},
{
"typeId": "2",
"offerId": "14"
},
{
"typeId": "2",
"offerId": "16"
}
]
Please help to achieve as expected.
You can transfer "id": "[&4].[&2].typeId" key-value pair into the object tagged "offerings" key name as "#(2,type.id)": "[&3].[&1].typeid" in order to combine them as desired such like the below one
[
{
"operation": "shift",
"spec": {
"*": {
"*": {
"*": {
"offerings": {
"*": {
"#(2,type.id)": "[&3].[&1].typeid",
"*": "[&3].[&1].offer&"
}
}
}
}
}
}
},
{
"operation": "shift",
"spec": {
"*": {
"*": "[]"
}
}
}
]
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"}]}
);
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"
}
]
}
]
}
]
}
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"
]
}
}
}
}
}
}
}
]
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!