Filtering on nested JSON array: Rest Assured - json

I am trying to filter my GET response(JSON) based on a value in a nested JSON array. For eg: In the following JSON i want to filter an JSON array and print the names of cakes using Chocolate as batter.
{
"id": "0001",
"type": "donut",
"name": "Choco Blueberry Cake",
"ppu": 0.55,
"batter":[
{ "id": "1001", "type": "Regular" },
{ "id": "1002", "type": "Chocolate" },
{ "id": "1003", "type": "Blueberry" }
]
}
I have tried something like:
List<String> chocolateCakeList =jsonPath.getList("findAll{it.batter.type=='chocolate'}.name");
and
List<String> chocolateCakeList =jsonPath.getList("findAll{it.batter.it.type=='chocolate'}.name");
Both return empty Lists.

Problem
First, if you want to use findAll then the object to be axtract must be an array. Your json is object {}, not an array []. Actually, your nested object batter is an array [].
keyword to search is Chocolate, not chocolate. Case-sensitive is applied here.
Solution
-If your whole response is exactly what you posted, then the path to extract is
String name = jsonPath.getString("name")
-If your response has structrure like this.
[
{
"id": "0001",
"type": "donut",
"name": "Choco Blueberry Cake",
"ppu": 0.55,
"batter": [
{
"id": "1001",
"type": "Regular"
},
{
"id": "1002",
"type": "Chocolate"
},
{
"id": "1003",
"type": "Blueberry"
}
]
},
{
"id": "0002",
"type": "donut",
"name": "Choco Blueberry Cake",
"ppu": 0.55,
"batter": [
{
"id": "1001",
"type": "Regular"
},
{
"id": "1002",
"type": "Chocolate 2"
},
{
"id": "1003",
"type": "Blueberry"
}
]
}
]
Then the extraction is
List<String> list = jsonPath.getList("findAll {it.batter.findAll {it.type == 'Chocolate'}}.name");

Related

Printing JSON like console.log prints it in Node.js

Wondering if it's possible to print JSON like Node.js prints it out. If there is some standard module or something to do that.
It has the spacing between keys, and when it's too long it goes onto a new line, etc. The coloring would be a bonus.
JSON.stringify(object, null, 2) pretty prints the JSON, wondering if there is something more hidden in there, or any standards, for doing it like Node.js does. Thank you.
This seems to be achievable by using util.inspect():
const util = require('util');
const testJson = `{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" },
{ "id": "1002", "type": "Chocolate" },
{ "id": "1003", "type": "Blueberry" },
{ "id": "1004", "type": "Devil's Food" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5007", "type": "Powdered Sugar" },
{ "id": "5006", "type": "Chocolate with Sprinkles" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
}`
x = JSON.parse(testJson);
x.x = x;
console.log(util.inspect(x, { colors: true }));
The options object takes a parameter called depth that determines how deep it will recurse. The default value is 2. If I increase it to 3:
console.log(util.inspect(x, { colors: true, depth: 3 }));
I get the following:
To make it recurse indefinitely pass depth: null. The default value seems to be 2 in the node cli as well.

Extracting lines from nested json file using Ubuntu

I have nested json file (each field can have one or more sons) with many lines. Something like this:
{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" },
{ "id": "1002", "type": "Chocolate" },
{ "id": "1003", "type": "Blueberry" },
{ "id": "1004", "type": "Devil's Food" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5007", "type": "Powdered Sugar" },
{ "id": "5006", "type": "Chocolate with Sprinkles" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
}
Using Ubuntu (or Unix) I would like to find the first 10 lines that their "batters" field is not empty (i.e. in the line one or more of its sons contain value (not null or "").

How to flatten two json arrays using apache drill

{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" },
{ "id": "1002", "type": "Chocolate" },
{ "id": "1003", "type": "Blueberry" },
{ "id": "1004", "type": "Devil's Food" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5007", "type": "Powdered Sugar" },
{ "id": "5006", "type": "Chocolate with Sprinkles" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
}
I have the above json and i want to flatten both batter and topping arrays.
so i tried doing:
SELECT flatten(topping) as toping,flatten(batters.batter) as bat FROM json.jsonfiles.`batter.json`;
which gives me
org.apache.drill.common.exceptions.UserRemoteException: VALIDATION
ERROR: From line 1, column 43 to line 1, column 49: Table 'batters'
not found SQL Query null [Error Id:
33cf80f2-f283-4401-90ce-c262474e0778 on acer:31010]
How can i solve this? Can we flatten two arrays in a single query?
You need to add table alias and refer it in columns. Below query works for me with sample data you have provided.
SELECT flatten(a.topping) as toping,flatten(a.batters.batter) as bat FROM dfs.tmp.`batter.json` a;

Parsing JSON with arrays and structures with Coldfusion

I need to output the JSON result in HTML so that I can use it in Coldfusion. I am getting the data but I do not know how to parse the returned data so that I can use it. I am a newby so be easy on me. I don't know JSON at all and this is the first time I am trying to work work this.
<cfset qpxFields = {
"request": {
"passengers": {
"adultCount": "1"
},
"slice": [
{
"origin": "JNB",
"destination": "MRU",
"date": "2016-12-19"
}
],
"solutions": "1"
}
}/>
<cfhttp url="https://www.googleapis.com/qpxExpress/v1/trips/search?key=AIzaSyB0NN9WYmrkc2Ikq9TVGzzAD_gGoSBSbP4" method="post" result="httpResp" timeout="60">
<cfhttpparam type="header" name="Content-Type" value="application/json" />
<cfhttpparam type="body" value="#serializeJSON(qpxFields)#">
</cfhttp>
<cfset getResult = deserializeJSON(httpResp.filecontent)>
<cfoutput>#httpResp.filecontent#</cfoutput>
The result I am getting when outputting the filecontent is the following:
{ "kind": "qpxExpress#tripsSearch", "trips": { "kind": "qpxexpress#tripOptions", "requestId": "ylROS8N2kR4vI8ktC0PQVj", "data": { "kind": "qpxexpress#data", "airport": [ { "kind": "qpxexpress#airportData", "code": "JNB", "city": "JNB", "name": "Johannesburg O.R. Tambo International" }, { "kind": "qpxexpress#airportData", "code": "MRU", "city": "MRU", "name": "Mauritius Sir S. Ramgoolam International" } ], "city": [ { "kind": "qpxexpress#cityData", "code": "JNB", "name": "Johannesburg" }, { "kind": "qpxexpress#cityData", "code": "MRU", "name": "Mauritius" } ], "aircraft": [ { "kind": "qpxexpress#aircraftData", "code": "343", "name": "Airbus A340" } ], "tax": [ { "kind": "qpxexpress#taxData", "id": "EV_001", "name": "South Africa Passenger Safety Charge" }, { "kind": "qpxexpress#taxData", "id": "YQ_F", "name": "MK YQ surcharge" }, { "kind": "qpxexpress#taxData", "id": "YR_I", "name": "MK YR surcharge" }, { "kind": "qpxexpress#taxData", "id": "ZA_001", "name": "South Africa Passenger Service Charge" }, { "kind": "qpxexpress#taxData", "id": "UM_001", "name": "South Africa Asc Charge" }, { "kind": "qpxexpress#taxData", "id": "WC_001", "name": "South Africa Air Passenger Tax" } ], "carrier": [ { "kind": "qpxexpress#carrierData", "code": "MK", "name": "AIR MAURITIUS LTD" } ] }, "tripOption": [ { "kind": "qpxexpress#tripOption", "saleTotal": "ZAR5398.23", "id": "bGXAC5TFGRFO06xEFBzMaA001", "slice": [ { "kind": "qpxexpress#sliceInfo", "duration": 240, "segment": [ { "kind": "qpxexpress#segmentInfo", "duration": 240, "flight": { "carrier": "MK", "number": "852" }, "id": "GB3DFc4zHshnkF7H", "cabin": "COACH", "bookingCode": "T", "bookingCodeCount": 9, "marriedSegmentGroup": "0", "leg": [ { "kind": "qpxexpress#legInfo", "id": "LwsDBsjHUFZrYe5Y", "aircraft": "343", "arrivalTime": "2016-12-19T19:35+04:00", "departureTime": "2016-12-19T13:35+02:00", "origin": "JNB", "destination": "MRU", "originTerminal": "B", "duration": 240, "mileage": 1904, "meal": "Meal" } ] } ] } ], "pricing": [ { "kind": "qpxexpress#pricingInfo", "fare": [ { "kind": "qpxexpress#fareInfo", "id": "AdGb1tIdX7T9uIyT9qTU9OFHTXhaVL0C0ojKd7a7use6", "carrier": "MK", "origin": "JNB", "destination": "MRU", "basisCode": "TAANOWMU" } ], "segmentPricing": [ { "kind": "qpxexpress#segmentPricing", "fareId": "AdGb1tIdX7T9uIyT9qTU9OFHTXhaVL0C0ojKd7a7use6", "segmentId": "GB3DFc4zHshnkF7H" } ], "baseFareTotal": "ZAR3690.00", "saleFareTotal": "ZAR3690.00", "saleTaxTotal": "ZAR1708.23", "saleTotal": "ZAR5398.23", "passengers": { "kind": "qpxexpress#passengerCounts", "adultCount": 1 }, "tax": [ { "kind": "qpxexpress#taxInfo", "id": "ZA_001", "chargeType": "GOVERNMENT", "code": "ZA", "country": "ZA", "salePrice": "ZAR346.00" }, { "kind": "qpxexpress#taxInfo", "id": "EV_001", "chargeType": "GOVERNMENT", "code": "EV", "country": "ZA", "salePrice": "ZAR20.23" }, { "kind": "qpxexpress#taxInfo", "id": "UM_001", "chargeType": "GOVERNMENT", "code": "UM", "country": "ZA", "salePrice": "ZAR24.00" }, { "kind": "qpxexpress#taxInfo", "id": "WC_001", "chargeType": "GOVERNMENT", "code": "WC", "country": "ZA", "salePrice": "ZAR190.00" }, { "kind": "qpxexpress#taxInfo", "id": "YQ_F", "chargeType": "CARRIER_SURCHARGE", "code": "YQ", "salePrice": "ZAR1090.00" }, { "kind": "qpxexpress#taxInfo", "id": "YR_I", "chargeType": "CARRIER_SURCHARGE", "code": "YR", "salePrice": "ZAR38.00" } ], "fareCalculation": "JNB MK MRU 260.69TAANOWMU NUC 260.69 END ROE 14.15458 FARE ZAR 3690.00 XT 20.23EV 24.00UM 190.00WC 346.00ZA 1090.00YQ 38.00YR", "latestTicketingTime": "2016-12-19T06:34-05:00", "ptc": "ADT", "refundable": true } ] } ] } }
I am using CF 10.
Instead of trying to deal with the HTTP response (httpResp.filecontent) look at your deserialized content (getResult). You cannot simply output that variable as ColdFusion creates a structure from the JSON data.
Dump out your deserialzed JSON like this:
<cfdump var="#getResult#">
Looking at that output you will see how ColdFusion has already parsed all of the information for you. You are going to have some structure values and some array values. You will need to use appropriate methods (looping over an array for example) to extract each individual piece of data.
Reply to your comment
Looping in ColdFusion is well documented. To get you started you can look at the Adobe documentation itself - cfloop. The documentation on that page shows how to link over arrays, structures, etc.
Another good reference is Learn CF In a Week - looping.
Looping works when you have to traverse one-dimensional or two-dimensional structs or arrays. When the data combines structs and arrays in 3 or more dimensions, as in this particular problem, then looping is often insufficient as a solution. The complexity will certainly overwhelm most beginners.
A good solution is to play dumb. Start with the result, the structure getResult. Do a dump, as suggested by others earlier. Then simply run through it by eye and drill down to the values.
The list of values is:
getResult.kind
getResult.trips.data.aircraft[1].code
getResult.trips.data.aircraft[1].kind
getResult.trips.data.aircraft[1].name
getResult.trips.data.airport[1].city
getResult.trips.data.airport[1].code
getResult.trips.data.airport[1].kind
getResult.trips.data.airport[1].name
getResult.trips.data.airport[2].city
getResult.trips.data.airport[2].code
getResult.trips.data.airport[2].kind
getResult.trips.data.airport[2].name
getResult.trips.data.carrier[1].code
getResult.trips.data.carrier[1].kind
getResult.trips.data.carrier[1].name
getResult.trips.data.city[1].code
getResult.trips.data.city[1].kind
getResult.trips.data.city[1].name
getResult.trips.data.city[2].code
getResult.trips.data.city[2].kind
getResult.trips.data.city[2].name
getResult.trips.data.kind
getResult.trips.data.tax[1].id
getResult.trips.data.tax[1].kind
getResult.trips.data.tax[1].name
getResult.trips.data.tax[2].id
getResult.trips.data.tax[2].kind
getResult.trips.data.tax[2].name
getResult.trips.data.tax[3].id
getResult.trips.data.tax[3].kind
getResult.trips.data.tax[3].name
getResult.trips.data.tax[4].id
getResult.trips.data.tax[4].kind
getResult.trips.data.tax[4].name
getResult.trips.data.tax[5].id
getResult.trips.data.tax[5].kind
getResult.trips.data.tax[5].name
getResult.trips.data.tax[6].id
getResult.trips.data.tax[6].kind
getResult.trips.data.tax[6].name
getResult.trips.kind
getResult.trips.requestId
getResult.trips.tripOption[1].id
getResult.trips.tripOption[1].kind
getResult.trips.tripOption[1].saletotal
getResult.trips.tripOption[1].pricing[1].basefareTotal
getResult.trips.tripOption[1].pricing[1].fare[1].basiscode
getResult.trips.tripOption[1].pricing[1].fare[1].carrier
getResult.trips.tripOption[1].pricing[1].fare[1].destination
getResult.trips.tripOption[1].pricing[1].fare[1].id
getResult.trips.tripOption[1].pricing[1].fare[1].kind
getResult.trips.tripOption[1].pricing[1].fare[1].origin
getResult.trips.tripOption[1].pricing[1].fareCalculation
getResult.trips.tripOption[1].pricing[1].kind
getResult.trips.tripOption[1].pricing[1].latestTicketingTime
getResult.trips.tripOption[1].pricing[1].passengers.adultCount
getResult.trips.tripOption[1].pricing[1].passengers.kind
getResult.trips.tripOption[1].pricing[1].ptc
getResult.trips.tripOption[1].pricing[1].refundable
getResult.trips.tripOption[1].pricing[1].saleFareTotal
getResult.trips.tripOption[1].pricing[1].saletaxTotal
getResult.trips.tripOption[1].pricing[1].saleTotal
getResult.trips.tripOption[1].pricing[1].segmentPricing[1].fareId
getResult.trips.tripOption[1].pricing[1].segmentPricing[1].kind
getResult.trips.tripOption[1].pricing[1].segmentPricing[1].segmentId
getResult.trips.tripOption[1].pricing[1].tax[1].chargeType
getResult.trips.tripOption[1].pricing[1].tax[1].code
getResult.trips.tripOption[1].pricing[1].tax[1].country
getResult.trips.tripOption[1].pricing[1].tax[1].id
getResult.trips.tripOption[1].pricing[1].tax[1].kind
getResult.trips.tripOption[1].pricing[1].tax[1].salePrice
getResult.trips.tripOption[1].pricing[1].tax[2].chargeType
getResult.trips.tripOption[1].pricing[1].tax[2].code
getResult.trips.tripOption[1].pricing[1].tax[2].country
getResult.trips.tripOption[1].pricing[1].tax[2].id
getResult.trips.tripOption[1].pricing[1].tax[2].kind
getResult.trips.tripOption[1].pricing[1].tax[2].salePrice
getResult.trips.tripOption[1].pricing[1].tax[3].chargeType
getResult.trips.tripOption[1].pricing[1].tax[3].code
getResult.trips.tripOption[1].pricing[1].tax[3].country
getResult.trips.tripOption[1].pricing[1].tax[3].id
getResult.trips.tripOption[1].pricing[1].tax[3].kind
getResult.trips.tripOption[1].pricing[1].tax[3].salePrice
getResult.trips.tripOption[1].pricing[1].tax[4].chargeType
getResult.trips.tripOption[1].pricing[1].tax[4].code
getResult.trips.tripOption[1].pricing[1].tax[4].country
getResult.trips.tripOption[1].pricing[1].tax[4].id
getResult.trips.tripOption[1].pricing[1].tax[4].kind
getResult.trips.tripOption[1].pricing[1].tax[4].salePrice
getResult.trips.tripOption[1].pricing[1].tax[5].chargeType
getResult.trips.tripOption[1].pricing[1].tax[5].code
getResult.trips.tripOption[1].pricing[1].tax[5].id
getResult.trips.tripOption[1].pricing[1].tax[5].kind
getResult.trips.tripOption[1].pricing[1].tax[5].salePrice
getResult.trips.tripOption[1].pricing[1].tax[6].chargeType
getResult.trips.tripOption[1].pricing[1].tax[6].code
getResult.trips.tripOption[1].pricing[1].tax[6].id
getResult.trips.tripOption[1].pricing[1].tax[6].kind
getResult.trips.tripOption[1].pricing[1].tax[6].salePrice
getResult.trips.tripOption[1].saletotal
getResult.trips.tripOption[1].slice[1].duration
getResult.trips.tripOption[1].slice[1].kind
getResult.trips.tripOption[1].slice[1].segment[1].bookingCode
getResult.trips.tripOption[1].slice[1].segment[1].bookingCodeCount
getResult.trips.tripOption[1].slice[1].segment[1].cabin
getResult.trips.tripOption[1].slice[1].segment[1].duration
getResult.trips.tripOption[1].slice[1].segment[1].flight.carrier
getResult.trips.tripOption[1].slice[1].segment[1].flight.number
getResult.trips.tripOption[1].slice[1].segment[1].id
getResult.trips.tripOption[1].slice[1].segment[1].kind
getResult.trips.tripOption[1].slice[1].segment[1].leg[1].aircraft
getResult.trips.tripOption[1].slice[1].segment[1].leg[1].arrivalTime
getResult.trips.tripOption[1].slice[1].segment[1].leg[1].departureTime
getResult.trips.tripOption[1].slice[1].segment[1].leg[1].destination
getResult.trips.tripOption[1].slice[1].segment[1].leg[1].duration
getResult.trips.tripOption[1].slice[1].segment[1].leg[1].id
getResult.trips.tripOption[1].slice[1].segment[1].leg[1].kind
getResult.trips.tripOption[1].slice[1].segment[1].leg[1].meal
getResult.trips.tripOption[1].slice[1].segment[1].leg[1].mileage
getResult.trips.tripOption[1].slice[1].segment[1].leg[1].origin
getResult.trips.tripOption[1].slice[1].segment[1].leg[1].originTerminal
getResult.trips.tripOption[1].slice[1].segment[1].marriedSegmentGroup

Schema to load json data to google big query

I have a question for the project that we are doing...
I tried to extract this JSON to Google Big Query and not able to get JSON votes Object fields from the JSON input. I tried the "record" and the "string" types in the schema.
{
"votes": {
"funny": 10,
"useful": 10,
"cool": 10
},
"user_id": "OlMjqqzWZUv2-62CSqKq_A",
"review_id": "LMy8UOKOeh0b9qrz-s1fQA",
"stars": 4,
"date": "2008-07-02",
"text": "This is what this 4-star bar is all about.",
"type": "review",
"business_id": "81IjU5L-t-QQwsE38C63hQ"
}
Also i am not able to get the tables populated from this below JSON for the categories and neighborhood JSON arrays? What should my schema be for these inputs? The docs didn't help much unfortunately in this case or maybe i am not looking at the right place..
{
"business_id": "Iu-oeVzv8ZgP18NIB0UMqg",
"full_address": "3320 S Hill St\nSouth East LA\nLos Angeles, CA 90007",
"schools": [
"University of Southern California"
],
"open": true,
"categories": [
"Medical Centers",
"Health and Medical"
],
"neighborhoods": [
"South East LA"
]
}
I am able to get the regular fields, but that's about it... Any help is appreciated!
For business it seems you want schools to be a repeated field. Your schema should be:
"schema": {
"fields": [
{
"name": "business_id",
"type": "string"
}.
{
"name": "full_address",
"type": "string"
},
{
"name": "schools",
"type": "string",
"mode": "repeated"
},
{
"name": "open",
"type": "boolean"
}
]
}
For votes it seems you want record. Your schema should be:
"schema": {
"fields": [
{
"name": "name",
"type": "string"
}.
{
"name": "votes",
"type": "record",
"fields": [
{
"name": "funny",
"type": "integer",
},
{
"name": "useful",
"type": "integer"
},
{
"name": "cool",
"type": "integer"
}
]
},
]
}
Source
I was also stuck on this problem, but the issue I faced was because one has to remember to flag the mode as repeated for the records source
Also please note that these cannot have a null value source