How to apply function to multiple fields in jq - jq

I try to reduce the size of a jq call. The current command is:
jq '.result | .[].newValueJson.action |= (. | tostring // .) | .[].oldValueJson.action |= (. | tostring // .) | .[].metadata.value |= (. | tostring // .)'
As you can see, the function "tostring" is being applied to "newValueJson.action", "oldValueJson.action" and "metadata.value" in just the same way. I am wondering if there is a more compact syntax so I only need to apply tostring once?
I extracted sample data show what is being done (this is not the full json tree).
Source:
{
"result": [{
"id": 1,
"action": {
"result": true,
"type": "filter_create"
},
"newValueJson": {
"action": "simulate"
},
"oldValueJson": {
"action": "enforce"
},
"metadata": {
"value": false
}
},
{
"id": 2,
"action": {
"result": true,
"type": "filter_create"
},
"newValueJson": {
"action": {
"mode": "simulate",
"timeout": 3600
}
},
"oldValueJson": {
"action": {
"mode": "enforce",
"timeout": 3600
}
},
"metadata": {
"value": "off"
}
}
]
}
Result:
[{
"id": 1,
"action": {
"result": true,
"type": "filter_create"
},
"newValueJson": {
"action": "simulate"
},
"oldValueJson": {
"action": "enforce"
},
"metadata": {
"value": "false"
}
},
{
"id": 2,
"action": {
"result": true,
"type": "filter_create"
},
"newValueJson": {
"action": "{\"mode\":\"simulate\",\"timeout\":3600}"
},
"oldValueJson": {
"action": "{\"mode\":\"enforce\",\"timeout\":3600}"
},
"metadata": {
"value": "off"
}
}
]
Thanks and Best.

You can group the actions together using (..) as below. Also instead of using the array notation .[], you can use map(..) to handle apply the filter expression inside the result array
.result | map((.newValueJson.action, .oldValueJson.action, .metadata.value ) |= (. | tostring // .))

Related

Simplify array of objects with children using JQ

From Wikidata, I get the following json:
# Sparql query
query=$(cat ./myquery.sparql)
response=$(curl -G --data-urlencode query="${query}" https://wikidata.org/sparql?format=json)
echo "${response}" | jq '.results.bindings'
[
{
"language": {
"type": "uri",
"value": "https://lingualibre.org/entity/Q100"
},
"wikidata": {
"type": "literal",
"value": "Q36157"
},
"code": {
"type": "literal",
"value": "lub"
}
},
{
"language": {
"type": "uri",
"value": "https://lingualibre.org/entity/Q101"
},
"wikidata": {
"type": "literal",
"value": "Q36284"
},
"code": {
"type": "literal",
"value": "srr"
}
}
]
I would like to have the keys directly paired with their values, such as :
[
{
"language": "https://lingualibre.org/entity/Q100",
"wikidata": "Q36157",
"iso": "lub"
},
{
"language": "https://lingualibre.org/entity/Q101",
"wikidata": "Q36284",
"iso": "srr"
}
]
I currently have a non-resilient code, which will break whenever the key names change :
jq 'map({"language":.language.value,"wikidata":.wikidata.value,"iso":.code.value})'
How to pair the keys with their values in a resilient way (not naming the keys) ?
I want to "prune" the child objects so to only keep the value.
You could use map_values which works like the outer map but for objects, i.e. it retains the object structure, including the field names:
jq 'map(map_values(.value))'
[
{
"language": "https://lingualibre.org/entity/Q100",
"wikidata": "Q36157",
"code": "lub"
},
{
"language": "https://lingualibre.org/entity/Q101",
"wikidata": "Q36284",
"code": "srr"
}
]
Note that this solution lacks the name conversion from code to iso.

Remove Quotation from HTTP reponse(string datatype) to pass in post API

I have an API returning data(string format) like this
84, 101, 115, 116
But when I call this in power automate the response I get thru HTTP post is with quotation marks
"84, 101, 115, 116"
Is there any way I can get it without quotation mark " ", As I need the output to send in another API which fails if I send it
with "".
The reason being it needs to pass the response to another API that accepts byte array
like this [84, 101, 115, 116]
currently, inflow it is being sent as ["84, 101, 115, 116"] which fails the API
I tried replace function but it doesn't work for my case.
I think you need to split up your texts into an array.
Start with initialising three variables as shown below ...
... as you can see, I initialised a string variable with your values, it doesn't show the quotes but it's declared as a string so when it treats it, the quotes will be there.
In the next steps, I initialise an array variable that has the following expression ...
split(replace(variables('Response'), ' ', ''), ',')
... and then a blank array that will store the resulting number values.
After the above, loop through each value that was found and add it to the number array, this will convert the value as a string to a numeric value.
The expression above is ... int(item())
That then produces this result and it's that array that can then be passed through to your next API call.
This is the JOSN definition that you can load into your own tenant to see the answer in its entirety.
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"For_each": {
"actions": {
"Append_to_array_variable": {
"inputs": {
"name": "Number Array",
"value": "#int(item())"
},
"runAfter": {},
"type": "AppendToArrayVariable"
}
},
"foreach": "#variables('String Array')",
"runAfter": {
"Initialize_Number_Array": [
"Succeeded"
]
},
"runtimeConfiguration": {
"concurrency": {
"repetitions": 1
}
},
"type": "Foreach"
},
"Initialize_Number_Array": {
"inputs": {
"variables": [
{
"name": "Number Array",
"type": "array"
}
]
},
"runAfter": {
"Initialize_String_Array": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"Initialize_String_Array": {
"inputs": {
"variables": [
{
"name": "String Array",
"type": "array",
"value": "#split(replace(variables('Response'), ' ', ''), ',')"
}
]
},
"runAfter": {
"Initialize__Response": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"Initialize__Response": {
"inputs": {
"variables": [
{
"name": "Response",
"type": "string",
"value": "84, 101, 115, 116"
}
]
},
"runAfter": {},
"type": "InitializeVariable"
},
"Initialize_variable": {
"inputs": {
"variables": [
{
"name": "Result",
"type": "array",
"value": "#variables('Number Array')"
}
]
},
"runAfter": {
"For_each": [
"Succeeded"
]
},
"type": "InitializeVariable"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {},
"triggers": {
"Recurrence": {
"evaluatedRecurrence": {
"frequency": "Month",
"interval": 12
},
"recurrence": {
"frequency": "Month",
"interval": 12
},
"type": "Recurrence"
}
}
},
"parameters": {}
}

mapping array of keys to array of values for substitution

Given this data, which is two distinct objects, one having an array of keys and the other a dictionary of key value pairs:
{
"servers": [
{
"location": "server4",
"services": [
"srv07",
"srv06",
"srv01",
"srv04"
]
},
{
"location": "server2",
"services": [
"srv07",
"srv02",
"srv05",
"srv03"
]
}
],
"release": {
"id": "release1",
"services": [
{
"service": "srv01",
"URL": "/srv01_service/v1.20.0"
},
{
"service": "srv02",
"URL": "/srv02_service/v1.14.0"
},
{
"service": "srv03",
"URL": "/srv03_service/v1.15.0"
},
{
"service": "srv04",
"URL": "/srv04_service/v1.18.0"
},
{
"service": "srv05",
"URL": "/srv05_service/v1.14.0"
},
{
"service": "srv06",
"URL": "/srv06_serv/v1.13.0"
},
{
"service": "srv07",
"URL": "/srv07_service/v1.19.0"
}
]
}
}
I am trying to produce this, the first object with the keys replaced with the values from the dictionary. NOTE: I would be fine with renaming services[] to URLs[] if it makes things easier.
{
"servers": [
{
"location": "server4",
"services": [
"/srv07_service/v1.19.0",
"/srv06_serv/v1.13.0",
"/srv01_service/v1.20.0",
"/srv04_service/v1.18.0"
]
},
{
"location": "server2",
"services": [
"/srv07_service/v1.19.0",
"/srv02_service/v1.14.0",
"/srv05_service/v1.14.0",
"/srv03_service/v1.15.0"
]
}
]
}
My latest attempt is close but returns something akin to a Cartesian.
. | .servers[].services[] = (.servers[] as $s | .release.services[] | select(.service as $v | $s.services[] | index($v)).URL) | {servers}
Create an INDEX to lookup in, then map each element you want to change according to the index.
jq '
INDEX(.release.services[]; .service) as $index
| {servers} | .servers[].services[] |= $index[.].URL
'
{
"servers": [
{
"location": "server4",
"services": [
"/srv07_service/v1.19.0",
"/srv06_serv/v1.13.0",
"/srv01_service/v1.20.0",
"/srv04_service/v1.18.0"
]
},
{
"location": "server2",
"services": [
"/srv07_service/v1.19.0",
"/srv02_service/v1.14.0",
"/srv05_service/v1.14.0",
"/srv03_service/v1.15.0"
]
}
]
}
Demo

Conditional select using jq

I have this below json format, I want to take the list of "id" which satisfies the condition
in this below I want to take the id which has matchers.value as dev-stack and status.state as active
{
"status": "success",
"data": [
{
"id": "b5e7f85d",
"matchers": [
{
"name": "stack",
"value": "dev-stack",
"isRegex": true
}
],
"startsAt": "2020-07-13T07:17:36Z",
"endsAt": "2020-07-15T07:15:44Z",
"updatedAt": "2020-07-13T07:15:59.643692023Z",
"createdBy": "api",
"comment": "Silence",
"status": {
"state": "active"
}
},
{
"id": "1fdaa4b5",
"matchers": [
{
"name": "stack",
"value": "qa-stack",
"isRegex": true
}
],
"startsAt": "2020-07-10T13:19:12Z",
"endsAt": "2020-07-10T13:20:55.510739499Z",
"updatedAt": "2020-07-10T13:20:55.510739499Z",
"createdBy": "api",
"comment": "Silence",
"status": {
"state": "expired"
}
}
]
}
Here is a solution which uses update assignment |=, map and select to update .data.
Note it avoids an undesirable cartesian product if multiple .matchers meet the criteria by using any.
.data |= map(select(
(.matchers | any(.value=="dev-stack")) and (.status.state=="active")
))
Try it online!

How Can I group by Gremlin Server (Titan 1.0) Response on Basis of Vertex Id?

I'm trying following query :
g.V(835776).out('Follow').in('WallPost').order().by('PostedTimeLong', decr).range(0,2)
and I'm getting following response :
{
"requestId": "524462bc-5e46-40bf-aafd-64d00351dc87",
"status": {
"message": "",
"code": 200,
"attributes": { }
},
"result": {
"data": [
{
"id": 1745112,
"label": "Post",
"type": "vertex",
"properties": {
"PostImage": [
{
"id": "sd97-11ejc-2wat",
"value": ""
}
],
"PostedByUser": [
{
"id": "sc2j-11ejc-2txh",
"value": "orbitpage#gmail.com"
}
],
"PostedTime": [
{
"id": "scgr-11ejc-2upx",
"value": "2016-06-19T09:17:27.6791521Z"
}
],
"PostMessage": [
{
"id": "sbob-11ejc-2t51",
"value": "Hello #[tag:Urnotice_Profile|835776|1] , #[tag:Abhinav_Srivastava|872488|1] and #[tag:Rituraj_Rathore|839840|1]"
}
],
"PostedTimeLong": [
{
"id": "scuz-11ejc-2vid",
"value": 636019246476802029
}
]
}
},
{
"id": 1745112,
"label": "Post",
"type": "vertex",
"properties": {
"PostImage": [
{
"id": "sd97-11ejc-2wat",
"value": ""
}
],
"PostedByUser": [
{
"id": "sc2j-11ejc-2txh",
"value": "orbitpage#gmail.com"
}
],
"PostedTime": [
{
"id": "scgr-11ejc-2upx",
"value": "2016-06-19T09:17:27.6791521Z"
}
],
"PostMessage": [
{
"id": "sbob-11ejc-2t51",
"value": "Hello #[tag:Urnotice_Profile|835776|1] , #[tag:Abhinav_Srivastava|872488|1] and #[tag:Rituraj_Rathore|839840|1]"
}
],
"PostedTimeLong": [
{
"id": "scuz-11ejc-2vid",
"value": 636019246476802029
}
]
}
}
],
"meta": { }
}
}
since same post is posted on two different Id's it is coming twice in response. I want to group by response on basis of vertex id ( both have same vertex id. or i just want to get one object out of them as both are same only.
I've tried following queries but nothing worked for me :
g.V(835776).out('Follow').in('WallPost').groupBy{it.id}.order().by('PostedTimeLong', decr).range(0,3)
g.V(835776).out('Follow').in('WallPost').group().by(id).order().by('PostedTimeLong', decr).range(0,3)
How can I group by the result on basis of vertex id.
The query
g.V(835776).out('Follow').in('WallPost').group().by(id).order().by('PostedTimeLong', decr).range(0,3)
should work, although order().by() and range() will have no effect. However, I don'tthink you really want to group(), you more likely want to dedup():
g.V(835776).out('Follow').in('WallPost').dedup().order().by('PostedTimeLong', decr).limit(3)

Resources