JSONpath, only return result if other element has a value - jsonpath

I am looking for the JSONpath expression to extract elements in an array only if it contains another element.
The following expression returns all elements;
$.differ.element[*]['id','alias']
This is the JSON file:
{
"differ": {
"element": [
{
"id": "Address",
"alias": [
"Information about address"
]
},
{
"id": "Address.extension",
"path": "Address.extension"
},
{
"id": "Address.extension:official",
"path": "Address.extension",
"alias": [
"Mark address"
]
}
]
}
}
This results in the following output:
[
"Address",
[
"Information about address"
],
"Address.extension",
"Address.extension:official",
[
"Mark address"
]
]
I would like to omit the 'Address.extension' element as it does not have an alias.
How can I achieve this?

You can try with this
$.differ.element[?(#.alias)]
will get output like this :
[
{
"id":"Address",
"alias":[
"Information about address"
]
},
{
"id":"Address.extension:official",
"path":"Address.extension",
"alias":[
"Mark address"
]
}
]

Related

How to find the parent keys of a jsonpath result

I have this json obj
{
"abc": {
"some_field": {
"title": "Token",
"type": "password"
},
"some_field_2": {
"title": "Domain",
"type": "text"
},
"some_field_3": {
"title": "token2",
"type": "password"
}
}
}
And I want to get a list of keys [some_field,some_field_3] where type=password
This jsonpath $..[?(#.type=='password')] returns:
[
{
"title": "Token",
"type": "password"
},
{
"title": "token2",
"type": "password"
},
]
What should I do?
Thanks.
You are almost there, just need to add a ~ to the end to get the key(s) instead of the value(s):
$..[?(#.type=='password')]~
Note: this might not work depending on your jsonpath engine. It works on https://jsonpath.com.

jq Contactenate arrays from two different files and save the output in the first file

Here's what I'm looking to do.
file1.json
{
"info": {
"id": "",
"name": "Text Fields",
"schema": "url"
},
"item": [
{
"name": "CompanyName Field",
"item": [
{
"name": "CompanyName is CompanyName1"
}
]
}
]
}
file2.json
[
{
"name": "Phone Field",
"item": [
{
"name": "Phone is 1234"
}
]
},
{
"name": "Job Field",
"item": [
{
"name": "Job is Job1"
}
]
}
]
Expected output after running jq
file1.json
{
"info": {
"id": "",
"name": "Text Fields",
"schema": "url"
},
"item": [
{
"name": "CompanyName Field",
"item": [
{
"name": "CompanyName is CompanyName1"
}
]
},
{
"name": "Phone Field",
"item": [
{
"name": "Phone is 1234"
}
]
},
{
"name": "Job Field",
"item": [
{
"name": "Job is Job1"
}
]
}
]
}
As a first step I tried to at least concatenate the arrays of the two files and get that as an output before trying to get them in the first file itself but that itself is not happening.
Here's what I tried
jq '.item .' file1.json file2.json
but I get the following error:
jq: error: syntax error, unexpected $end, expecting FORMAT or QQSTRING_START (Unix shell quoting issues?) at <top-level>, line 1:
.item .
jq: 1 compile error
I tried searching a lot, trust me. There are a lot of queries with similar titles but they all seem to be very specific problems when you look into each one. Please help.
Use --argfile to read in the second file into a variable, then += to add it to the existing array in .item
jq --argfile f file2.json '.item += $f' file1.json
{
"info": {
"id": "",
"name": "Text Fields",
"schema": "url"
},
"item": [
{
"name": "CompanyName Field",
"item": [
{
"name": "CompanyName is CompanyName1"
}
]
},
{
"name": "Phone Field",
"item": [
{
"name": "Phone is 1234"
}
]
},
{
"name": "Job Field",
"item": [
{
"name": "Job is Job1"
}
]
}
]
}

The language expression property '0' can't be evaluated, property name must be a string - ARM Template error while adding Key Vault access policy

I've been working on an issue and seem to be stuck, so asking on so in case anyone can help.
To describe the issue, I've got an existing Azure Key Vault setup, and wish to add a number of access policies to this resource group. It needs to be conditional as if the function name is "false" then that function should not be added to key vault access policy.
variable section:
"variables": {
"functionAccess": {
"value": [
{
"name": "[parameters('Function_1')]"
},
{
"name": "[parameters('Function_2')]"
},
{
"name": "[parameters('Function_3')]"
}
]
}
}
My Template :
{
"apiVersion": "2016-10-01",
"condition": "[not(equals(variables('functionAccess')[CopyIndex()].name, 'false'))]",
"copy": {
"batchSize": 1,
"count": "[length(variables('functionAccess'))]",
"mode": "Serial",
"name": "accessPolicies"
},
"name": "[concat(parameters('KeyVault_Name'), '/add')]",
"properties": {
"accessPolicies": [
{
"tenantId": "[subscription().tenantId]",
"objectId": "[if(not(equals(variables('functionAccess')[CopyIndex()].name, 'false')), reference(concat('Microsoft.Web/sites/', variables('functionAccess')[CopyIndex()].name), '2016-08-01', 'Full').identity.principalId, json('null'))]",
"permissions": {
"keys": [
"get",
"list"
],
"secrets": [
"get",
"list"
],
"certificates": [
"get",
"list"
]
}
}
]
},
"type": "Microsoft.KeyVault/vaults/accessPolicies"
}
When I deploy my ARM template for the azure key vault I got this error message:
The language expression property '0' can't be evaluated, property name must be a string.
also tried below, but same error:
{
"apiVersion": "2018-02-14",
"name": "[concat(parameters('KeyVault_Name'), '/add')]",
"properties": {
"copy": [
{
"batchSize": 1,
"count": "[length(variables('functionAccess'))]",
"mode": "serial",
"name": "accessPolicies",
"input": {
"condition": "[not(equals(variables('functionAccess')[copyIndex('accessPolicies')].name, 'false'))]",
"tenantId": "[subscription().tenantId]",
"objectId": "[if(not(equals(variables('functionAccess')[copyIndex('accessPolicies')].name, 'false')), reference(concat('Microsoft.Web/sites/', variables('functionAccess')[copyIndex('accessPolicies')].name), '2016-08-01', 'Full').identity.principalId, json('null'))]",
"permissions": {
"keys": [
"get",
"list"
],
"secrets": [
"get",
"list"
],
"certificates": [
"get",
"list"
]
}
}
}
]
},
"type": "Microsoft.KeyVault/vaults/accessPolicies"
}
There are a few options for dealing with filtering an array for copy operation. I deploy my ARM templates from PowerShell scripts and use PowerShell to setup parameter values. When I need special logic handle different inputs for different environments, I let PowerShell handle it.
If you must handle the filtering in ARM and you have the option to input a CSV list of functions, then perhaps the following will work. You can then use the functionAccessArray to iterate over in the copy operation.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
},
"variables": {
"functionAccessCsv": "Function-0,Function-1,false,Function-4,false,Function-6,Function-7",
"functionAccessFiltered": "[replace(replace(variables('functionAccessCsv'), 'false', ''), ',,', ',')]",
"functionAccessArray": "[split(variables('functionAccessFiltered'), ',')]"
},
"resources": [
],
"outputs": {
"functionAccessCsvFiltered": {
"type": "string",
"value": "[variables('functionAccessFiltered')]"
},
"functionAccessArray": {
"type": "array",
"value": "[variables('functionAccessArray')]"
}
}
}
The result:
I just had the same issue. By using an array parameter with a default value instead of a variable, I got it to work.
"parameters": {
"functionAccess": {
"type": "array",
"defaultValue": [
"value1",
"value2",
"value3"
]
}
}

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 to create multiple tabs of forms using angular json schema form?

I have been successfully using this awesome library and concept called json schema form.
https://www.npmjs.com/package/angular2-json-schema-form
Now using the schema patterns given I am able to generate a form based on a dynamically created schema from database. I want to convert the single form in multiple tabs. I.E I want to group certain kind of fields in one panel.
Is there any kind of support for this functionality? So that I can assign the css class according to the layout.
https://angular2-json-schema-form.firebaseapp.com/?set=ng-jsf&example=ng-jsf-flex-layout&framework=material-design&language=en
You can split group of fields into separate tabs using the fieldsets property.
See the following example from README.md:
{
"properties": {
"firstName": {
"type": "string",
"description": "First name"
},
"lastName": {
"type": "string",
"description": "Last name"
},
"email": {
"type": "string",
"description": "Email"
},
"notificationsFrequency": {
"type": "string",
"description": "Notifications frequency",
"widget": "select",
"oneOf": [
{
"description": "Daily",
"enum": [
"daily"
]
},
{
"description": "Weekly",
"enum": [
"weekly"
]
},
{
"description": "Monthly",
"enum": [
"monthly"
]
}
],
"default": "daily"
}
},
"fieldsets": [
{
"title": "Personal information",
"fields": [
"firstName",
"lastName",
"email"
]
},
{
"title": "Account settings",
"fields": [
"notificationsFrequency"
]
}
]
}

Resources