Parsing json with JQ : Where are the comma? - json

I've this type of data :
{
"cidr" : "X.X.X.X/27",
"defaultGateway" : "X.X.X.X",
"full" : false,
"id" : "X.X.X.X",
"ipAddressTab" : [
{
"alias_domain" : null,
"alias_name" : null,
"description" : "This is the network address for X.X.X.X/27",
"dnr_rr" : null,
"dns_domain" : null,
"environnement" : null,
"fdqn" : null,
"hostname" : null,
"ip" : "X.X.X.X",
"requester" : null,
"status" : "reserved",
"type" : "network"
},
{
"alias_domain" : null,
"alias_name" : null,
"description" : "This is the default gateway address for X.X.X.X/27",
"dnr_rr" : null,
"dns_domain" : null,
"environnement" : null,
"fdqn" : null,
"hostname" : null,
"ip" : "X.X.X.X",
"requester" : null,
"status" : "reserved",
"type" : "gateway"
},
{
"alias_domain" : "toto.com",
"alias_name" : "",
"description" : "this is a test",
"dns_domain" : "",
"environnement" : "test",
"fdqn" : "XXX",
"hostname" : "XXX",
"ip" : "X.X.X.X",
"requester" : "XXX",
"status" : "allocated",
"type" : "VM"
},
{
"alias_domain" : "toto.com",
"alias_name" : "",
"description" : "this is a test",
"dns_domain" : "",
"environnement" : "test",
"fdqn" : "XXX",
"hostname" : "XXX",
"ip" : "X.X.X.X",
"requester" : "XXX",
"status" : "allocated",
"type" : "VM"
},
{
"ip" : "X.X.X.X",
"status" : "reserved"
},
{
"ip" : "X.X.X.X",
"status" : "reserved"
},
{
"ip" : "X.X.X.X",
"status" : "reserved"
},
{
"ip" : "X.X.X.X",
"status" : "reserved"
},
{
"alias_domain" : null,
"alias_name" : null,
"description" : "This is the broadcast address for X.X.X.X/27",
"dnr_rr" : null,
"dns_domain" : null,
"environnement" : null,
"fdqn" : null,
"hostname" : null,
"ip" : "X.X.X.X",
"requester" : null,
"status" : "reserved",
"type" : "broadcast"
}
]
}
I want to extract the IPs with "reserved" as status but without extractig the data for the gateway/network/broadcast IPs :
cat myfile | jq '.ipAddressTab[] | select(.status == "reserved") | select(.type != "network") | select(.type != "gateway") | select(.type != "broadcast")'
The output is :
{
"ip": "X.X.X.X",
"status": "reserved"
}
{
"ip": "X.X.X.X",
"status": "reserved"
}
{
"ip": "X.X.X.X",
"status": "reserved"
}
{
"ip": "X.X.X.X",
"status": "reserved"
}
But where are the commas between each " IP part " ?
On my file, each part in Braces are separated by a comma :
{
"ip" : "X.X.X.X",
"status" : "reserved"
}, <=
{
"ip" : "X.X.X.X",
"status" : "reserved"
}, <=
{
"ip" : "X.X.X.X",
"status" : "reserved"
}, <=
{
"ip" : "X.X.X.X",
"status" : "reserved"
}, <=
There is a way to keep them when I parse my file with jq ?
Thanks !

JQ's input and output are streams of JSON entities. The items in those streams are not comma separated. Some JQ filters may emit more than one entity for each entity they read in. Some filters may not emit any entity for some of the entities that they read in.
In your case, your input is a stream of one object, and your output is a stream of multiple objects. This is because each single array input to the [] filter results in a stream of all of the items in the output. It sounds like you instead want your output to consist of one array of objects. Here are two broad ways to do it.
1. Use map instead of []
cat myfile | jq '.ipAddressTab | map(select(.status == "reserved") | select(.type != "network") | select(.type != "gateway") | select(.type != "broadcast"))'
The parameter to map is another filter. It will be applied to each item in the array, and all the entities emitted by that filter will be gathered into one new array.
2. Use [ ... ] to gather the results of a filter into an array
cat myfile | jq '.ipAddressTab | [ .[] | select(.status == "reserved") | select(.type != "network") | select(.type != "gateway") | select(.type != "broadcast") ]'
It might seem like putting values between square brackets is just creating an array with one entry, but in fact what this syntax means is to evaluate the filter between the brackets, take the entire stream of output from that filter and make an array out of it.
In fact, this is exactly how map is itself defined. But it's useful to know, because it lets you see how you might use [ ... ] in other ways to capture a sequence of values.

Related

Transforming JSON data and child objects into rows within MSSQL

My very first question after using this site for my own learning! Still a beginner so go easy on me :)
I am trying to format JSON data within MSSQL Server. I have a static JSON file which I can get to display via OPENROWSET, and populate a variable. This JSON file has a "header" and then one or more "child" rows, basically an order header and order detail lines. I can successfully separately display the header's columns as a table in a result-set. I'd like to do the same with just the detail lines - the aim being to then store the header in a table and it's details in a table within SQL server - this part I'll have no issue with.
Here is some mock-up JSON data that I'm working with. This is the exact format I need to use, so I don't have any room to manoeuvre with it but I've populated it with test data:
{
"InputParameters" : {
"P_IN_ORDER_SOURCE" : "The_Web",
"P_IN_ORIG_SYS_DOCUMENT_REF" : "Order666",
"P_IN_SOLD_TO_CUST_NUMBER" : "JOEB11",
"P_IN_CUST_ORDER_NUMBER" : "JoeB5556667",
"P_IN_REQUEST_DATE" : "2021-01-20 08:10:06",
"P_IN_ORDER_ENTRY_DATE" : "2021-01-20 08:10:06",
"P_IN_SHIPTO_NAME" : "The Testing Co.",
"P_IN_SHIPTO_ADDR" : "82 Annweir Crescent",
"P_IN_SHIPTO_ADDR_2" : null,
"P_IN_SHIPTO_CITY" : "Atlantis",
"P_IN_SHIPTO_STATE" : "WSX",
"P_IN_SHIPTO_ZIP" : "AT55 666",
"P_IN_SHIPTO_COUNTRY" : "GB",
"P_IN_OPERATION_CODE" : "CREATE",
"P_IN_BOOKED_FLAG" : "N",
"P_IN_OU_NAME" : "ATL UK OU",
"P_IN_SPECIAL_INSTRUCTIONS" : null,
"P_IN_QUOTE_NUMBER" : null,
"P_IN_PRICELIST_ID" : "8",
"P_IN_EMAIL" : "testemail#testemail.com",
"P_IN_SHIPTO_COUNTY" : null,
"P_IN_SHIPPING_METHOD" : "Pre 930",
"P_IN_SHIPPING_INSTRUCTIONS" : null,
"P_IN_ATTENTION_TO" : "Joe Bloggs",
"P_IN_FREIGHT_CARRIER_CODE" : null,
"P_IN_IS_RETURN" : null,
"P_IN_SALES_REP" : null,
"P_IN_LINE_DATA" : [ {
"P_IN_LINE_DATA_ITEM" : [ {
"ORIG_SYS_DOCUMENT_REF" : "Order666",
"ORIG_SYS_LINE_REF" : "1",
"CUSTOMER_LINE_NUMBER" : "1",
"ITEM_TYPE_CODE" : "STANDARD",
"ITEM_DESCRIPTION" : "SKU7776",
"USER_ITEM_DESCRIPTION" : "SKU7776",
"TOP_MODEL_LINE_REF" : null,
"LINK_TO_LINE_REF" : null,
"COMPONENT_CODE" : null,
"ORDERED_QUANTITY" : "6",
"ORDER_QUANTITY_UOM" : null,
"UNIT_LIST_PRICE" : "16.95",
"UNIT_SELLING_PRICE" : "16.95",
"CALCULATE_PRICE_FLAG" : "N",
"OPERATION_CODE" : "INSERT"
}, {
"ORIG_SYS_DOCUMENT_REF" : "Order666",
"ORIG_SYS_LINE_REF" : "2",
"CUSTOMER_LINE_NUMBER" : "2",
"ITEM_TYPE_CODE" : "STANDARD",
"ITEM_DESCRIPTION" : "SKU12345",
"USER_ITEM_DESCRIPTION" : "SKU12345",
"TOP_MODEL_LINE_REF" : null,
"LINK_TO_LINE_REF" : null,
"COMPONENT_CODE" : null,
"ORDERED_QUANTITY" : "6",
"ORDER_QUANTITY_UOM" : null,
"UNIT_LIST_PRICE" : "11.89",
"UNIT_SELLING_PRICE" : "11.89",
"CALCULATE_PRICE_FLAG" : "N",
"OPERATION_CODE" : "INSERT"
}, {
"ORIG_SYS_DOCUMENT_REF" : "Order666",
"ORIG_SYS_LINE_REF" : "3",
"CUSTOMER_LINE_NUMBER" : "3",
"ITEM_TYPE_CODE" : "STANDARD",
"ITEM_DESCRIPTION" : "SKU9999",
"USER_ITEM_DESCRIPTION" : "SKU9999",
"TOP_MODEL_LINE_REF" : null,
"LINK_TO_LINE_REF" : null,
"COMPONENT_CODE" : null,
"ORDERED_QUANTITY" : "8",
"ORDER_QUANTITY_UOM" : null,
"UNIT_LIST_PRICE" : "46.42",
"UNIT_SELLING_PRICE" : "46.42",
"CALCULATE_PRICE_FLAG" : "N",
"OPERATION_CODE" : "INSERT"
} ]
} ]
}
}
I've been trying to learn how to use this JSON with SQL server pretty much starting from today. I've explored the OPENJSON() function which like I've said, I can define the separate columns and path with the header information - but as soon as I try to do similar and path to the detail objects, I just get NULLs back in each column.
Any suggestions at all? Apologies if I've missed any key information out here! Many thanks!
Something like this:
declare #json nvarchar(max) = '
{
"InputParameters" : {
"P_IN_ORDER_SOURCE" : "The_Web",
"P_IN_ORIG_SYS_DOCUMENT_REF" : "Order666",
"P_IN_SOLD_TO_CUST_NUMBER" : "JOEB11",
"P_IN_CUST_ORDER_NUMBER" : "JoeB5556667",
"P_IN_REQUEST_DATE" : "2021-01-20 08:10:06",
"P_IN_ORDER_ENTRY_DATE" : "2021-01-20 08:10:06",
"P_IN_SHIPTO_NAME" : "The Testing Co.",
"P_IN_SHIPTO_ADDR" : "82 Annweir Crescent",
"P_IN_SHIPTO_ADDR_2" : null,
"P_IN_SHIPTO_CITY" : "Atlantis",
"P_IN_SHIPTO_STATE" : "WSX",
"P_IN_SHIPTO_ZIP" : "AT55 666",
"P_IN_SHIPTO_COUNTRY" : "GB",
"P_IN_OPERATION_CODE" : "CREATE",
"P_IN_BOOKED_FLAG" : "N",
"P_IN_OU_NAME" : "ATL UK OU",
"P_IN_SPECIAL_INSTRUCTIONS" : null,
"P_IN_QUOTE_NUMBER" : null,
"P_IN_PRICELIST_ID" : "8",
"P_IN_EMAIL" : "testemail#testemail.com",
"P_IN_SHIPTO_COUNTY" : null,
"P_IN_SHIPPING_METHOD" : "Pre 930",
"P_IN_SHIPPING_INSTRUCTIONS" : null,
"P_IN_ATTENTION_TO" : "Joe Bloggs",
"P_IN_FREIGHT_CARRIER_CODE" : null,
"P_IN_IS_RETURN" : null,
"P_IN_SALES_REP" : null,
"P_IN_LINE_DATA" : [ {
"P_IN_LINE_DATA_ITEM" : [ {
"ORIG_SYS_DOCUMENT_REF" : "Order666",
"ORIG_SYS_LINE_REF" : "1",
"CUSTOMER_LINE_NUMBER" : "1",
"ITEM_TYPE_CODE" : "STANDARD",
"ITEM_DESCRIPTION" : "SKU7776",
"USER_ITEM_DESCRIPTION" : "SKU7776",
"TOP_MODEL_LINE_REF" : null,
"LINK_TO_LINE_REF" : null,
"COMPONENT_CODE" : null,
"ORDERED_QUANTITY" : "6",
"ORDER_QUANTITY_UOM" : null,
"UNIT_LIST_PRICE" : "16.95",
"UNIT_SELLING_PRICE" : "16.95",
"CALCULATE_PRICE_FLAG" : "N",
"OPERATION_CODE" : "INSERT"
}, {
"ORIG_SYS_DOCUMENT_REF" : "Order666",
"ORIG_SYS_LINE_REF" : "2",
"CUSTOMER_LINE_NUMBER" : "2",
"ITEM_TYPE_CODE" : "STANDARD",
"ITEM_DESCRIPTION" : "SKU12345",
"USER_ITEM_DESCRIPTION" : "SKU12345",
"TOP_MODEL_LINE_REF" : null,
"LINK_TO_LINE_REF" : null,
"COMPONENT_CODE" : null,
"ORDERED_QUANTITY" : "6",
"ORDER_QUANTITY_UOM" : null,
"UNIT_LIST_PRICE" : "11.89",
"UNIT_SELLING_PRICE" : "11.89",
"CALCULATE_PRICE_FLAG" : "N",
"OPERATION_CODE" : "INSERT"
}, {
"ORIG_SYS_DOCUMENT_REF" : "Order666",
"ORIG_SYS_LINE_REF" : "3",
"CUSTOMER_LINE_NUMBER" : "3",
"ITEM_TYPE_CODE" : "STANDARD",
"ITEM_DESCRIPTION" : "SKU9999",
"USER_ITEM_DESCRIPTION" : "SKU9999",
"TOP_MODEL_LINE_REF" : null,
"LINK_TO_LINE_REF" : null,
"COMPONENT_CODE" : null,
"ORDERED_QUANTITY" : "8",
"ORDER_QUANTITY_UOM" : null,
"UNIT_LIST_PRICE" : "46.42",
"UNIT_SELLING_PRICE" : "46.42",
"CALCULATE_PRICE_FLAG" : "N",
"OPERATION_CODE" : "INSERT"
} ]
} ]
}
}
'
select *
from openjson(#json,'$.InputParameters.P_IN_LINE_DATA[0].P_IN_LINE_DATA_ITEM')
with
(
ORIG_SYS_DOCUMENT_REF varchar(200),
ORIG_SYS_LINE_REF int,
CUSTOMER_LINE_NUMBER int,
ITEM_TYPE_CODE varchar(200),
-- . . .
OPERATION_CODE varchar(200)
)

JSON file to CSV file conversion using jq

I am trying to convert my json file to a csv file using jq. Below is the sample input events.json file.
{
"took" : 111,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "alerts",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"alertID" : "639387c3-0fbe-4c2b-9387-c30fbe7c2bc6",
"alertCategory" : "Server Alert",
"description" : "Successfully started.",
"logId" : null
}
},
{
"_index" : "alerts",
"_type" : "_doc",
"_id" : "2",
"_score" : 1.0,
"_source" : {
"alertID" : "2",
"alertCategory" : "Server Alert",
"description" : "Successfully stoped.",
"logId" : null
}
}
]
}
}
My rows in csv should have the data inside each _source tag. So my columns would be alertId , alertCategory , description and logId with its respective data.
I tried the below command :
jq --raw-output '.hits[] | [."alertId",."alertCategory",."description",."logId"] | #csv' < /root/events.json
and its not working.
Can anyone help me with this?
Your path-expression is not right, you have a hits array inside an object named hits and the fields you trying to put in CSV is present under __source object.
So your expression should have been below. Use it along with -r flag to put the output in raw output format
.hits.hits[]._source | [ .alertID, .alertCategory, .description, .logId ] | #csv
If your fields are null, the string representation of your null field value results in just "". If you want an explicit "null" string representation, use the alternate operator along with the field you expect to be null, e.g. instead of .logId, you can do (.logId // "null")
To add the column name as the header in the output CSV format, you could use the #csv or the join(",") function in raw output format -r
[ "alertId" , "alertCategory" , "description", "logId" ],
( .hits.hits[]._source | [ .alertID, .alertCategory, .description, .logId // "null" ]) | #csv
or
[ "alertId" , "alertCategory" , "description", "logId" ],
( .hits.hits[]._source | [ .alertID, .alertCategory, .description, .logId // "null" ]) | join(",")

Using Curl and PUT request to edit JSON file

I'm trying to edit an endpoint on a REST API that gives me an array of objects. I want to edit the json file but I've been having trouble with formatting the HTTP request.
the output of the endpoint is something like
"result" : [
{
"MAC" : "00:08:00:4A:A1:B3",
"available" : true,
"bridge" : "br0",
"ipv4" : {
"dns1" : "",
"dns2" : "",
"gateway" : "",
"ip" : "",
"mask" : "",
"mode" : ""
},
"ipv6" : {
"delegatedPrefixLength" : 64,
"dns1" : "",
"dns2" : "",
"enabled" : false,
"fixedIp" : [],
"gateway" : "",
"ip" : [],
"linkLocalIp" : [],
"mode" : "DELEGATED",
"prefixDelegationEnabled" : false
},
"name" : "eth0",
"nitype" : "ETHER",
"type" : "LAN"
},
{
"available" : false,
"bridge" : "br0",
"ipv4" : {
"dns1" : "",
"dns2" : "",
"gateway" : "",
"ip" : "",
"mask" : "",
"mode" : ""
},
"ipv6" : {
"delegatedPrefixLength" : 64,
"dns1" : "",
"dns2" : "",
"enabled" : false,
"fixedIp" : [],
"gateway" : "",
"ip" : [],
"linkLocalIp" : [],
"mode" : "DELEGATED",
"prefixDelegationEnabled" : false
},
"name" : "eth1",
"nitype" : "ETHER",
"type" : "LAN"
}
]
I need to be able to append some fields in the first object in the array. I have tried
curl -k -X PUT -H "Content-Type: application/json" -d '{[{"ipv4":{"mode":"DHCP"},"name": "eth0", "type":WAN}]"}' https://192.168.2.1/api/ni?token=$token1
but I keep getting an error saying that it's expecting a and object/value/array.
Any suggestions?
It looks like your PUT data does not have a top-level JSON field:
{[{"ipv4":{"mode":"DHCP"}, ...
The API is probably expecting something like this:
{"request": [{"ipv4":{"mode":"DHCP"}, ...
Check your documentation & examples for that API.

How to get a JSON node that contains a specific value?

Below is the JSON file I am trying to read nodes from. I am trying to perform contains operation. I do not want to use equals option in my json path like this - $.[?(#.name=="College Graduate - Ford")]
Could you please help me in meeting my requirement?
[
{
"incentiveId" : 123,
"autoApplied" : "false",
"name" : "College Graduate - Ford",
"amount" : 750,
"expirationDate" : "2018-12-31",
"minimumTerm" : null,
"maximumTerm" : null,
"groupAffiliation" : "College/Student",
"previousOwnership" : null
},
{
"incentiveId" : 456,
"autoApplied" : "false",
"name" : "Lease Loyalty - Ford",
"amount" : 500,
"expirationDate" : "2018-07-09",
"groupAffiliation" : null,
"previousOwnership" : "Lease Loyalty"
},
{
"incentiveId" : 789,
"autoApplied" : "false",
"name" : "Customer Cash - Ford",
"amount" : 1000,
"expirationDate" : "2018-06-04",
"groupAffiliation" : null,
"previousOwnership" : null
},
{
"incentiveId" : 222,
"autoApplied" : "false",
"name" : "Military - Ford",
"amount" : 1000,
"expirationDate" : "2018-12-31",
"groupAffiliation" : "Military",
"previousOwnership" : null
}
]
$.[?(/College/.test(#.name))]
Here I am using the test the RegExp test( ) method (which JSONPath evals behind the scenes) . This will perform the contains operation.
you can use filter to get array from array which elements satisfy the condition.
colleagues = json.filter(node => node.name.match("College"))
result:
[
{
"incentiveId": 123,
"autoApplied": "false",
"name": "College Graduate - Ford",
"amount": 750,
"expirationDate": "2018-12-31",
"minimumTerm": null,
"maximumTerm": null,
"groupAffiliation": "College/Student",
"previousOwnership": null
}
]

How to delete a info with ID from JSON based data

The content of my JSON file is:
This is my retails.json file.actually retails is my database.i converted this json file from sql database.so in this json file, I want to delete a person information with a single ID.How can i do? i am using node.js and express.
{
"categories" : [
{
"dept_id" : "123",
"category_name" : "database",
"category_discription" : "list of database",
"current time" : "2016-07-21 06:27:17",
"id" : "1"
},
{
"dept_id" : "1234",
"category_name" : "debugging",
"category_discription" : "program debugger",
"current time" : "2016-07-21 06:32:24",
"id": "2"
},
{
"dept_id" : "12345",
"category_name" : "system analyzer",
"category_discription" : null,
"current time" : "2016-07-21 06:33:23",
"id" : "3"
}
],
"departments" : [
{
"name" : "manpreet singh",
"address_info" : "qadian",
"current time" : null,
"id" : "1"
},
{
"name" : "tushal gupta",
"address_info" : "amritsar",
"current time" : "2016-07-21 06:10:14",
"id" : "2"
},
{
"name" : "haroop singh",
"address_info" : "amritsar",
"current time" : "2016-07-21 06:11:12",
"id" : "3"
}
],
"digital_marketing" : [
{
"dept_id" : "123",
"phone" : "99889988",
"mobile" : null,
"email" : "thbs#gmail.com",
"web" : null,
"facebook" : null,
"twitter" : null,
"linkedin" : null,
"current time" : "2016-07-21 06:10:16",
"id" : "1"
},
{
"dept_id" : "1234",
"phone" : "998899888",
"mobile" : null,
"email" : null,
"web" : null,
"facebook" : "gtudgal#fb.com",
"twitter" : "tushalgupta",
"linkedin" : null,
"current time" : "2016-07-21 06:30:19",
"id" : "2"
},
{
"dept_id" : "12345",
"phone" : "99889877",
"mobile" : null,
"email" : "fhdts#mail.com",
"web" : null,
"facebook":"sdfh33#fb.com",
"twitter" : null,
"linkedin" : null,
"current time" : "2016-07-21 06:30:13",
"id" : "3"
}
]
}
I am using this to delete a ID, but does not work:
var id = 2;
app.get('/deleteUser', function (req, res) {
// First read existing users.
fs.readFile( __dirname + "/" + "retails.json", 'utf8', function (err, data) {
data = JSON.parse( data );
delete data["categories" + 2];
console.log( data );
res.end( JSON.stringify(data));
});
});
for (var prop in jsonObj.categories){
delete jsonObj.categories[prop].id;
}
similar for digital_marketing etc. jsonObj is the data in your case..