i have an array converted to a json ($user_data_JSON = $user_data | ConvertTo-Json) in powershell which looks like this
$user_data_JSON
{
[
{
"targetId": "5007Y00000K5nkjQAB",
"login": "login1",
"password": "scRHDztkKbO"
},
{
"targetId": "5007Y00000MNbDvQAL",
"login": "login2",
"password": "scRHDztkKbO"
}
]
}
But i need to modify it like this with a KEY value on top:
$user_data_JSON
{
"logins":[
{
"targetId": "5007Y00000K5nkjQAB",
"login": "login1",
"password": "scRHDztkKbO"
},
{
"targetId": "5007Y00000MNbDvQAL",
"login": "login2",
"password": "scRHDztkKbO"
}
]
}
How can I manage to achieve this?
I've already tried to create a new array object, add the key and convert it to a json file like this:
$jsonBase = #{}
$list = New-Object System.Collections.ArrayList
$list.Add("Foo")
$list.Add("Bar")
$jsonBase.Add("Data",$list)
$jsonBase | ConvertTo-Json
To get something like this:
{
"Data": [
"Foo",
"Bar"
]
}
but when I convert my array to a json again, it looks kind of trunkated:
$jsonBase | ConvertTo-Json -Depth 10
{
"logins": [
"[\r\n {\r\n \"targetId\": \"5007Y00000K5nkjQAB\",\r\n \"login\": \"login1\",\r\n \"password\": \"scRHDztkKbO\"\r\n },\r\n {\r\n
\"targetId\": \"5007Y00000MNbDvQAL\",\r\n \"login\": \"login2\",\r\n \"password\": \"scRHDztkKbO\"\r\n },"
]
}
How can I get a propoer JSON object?
Thanks
Don't use the JSON (text) representation of your array ($user_data_JSON), use its original, object form ($user_data) to construct a wrapper object with the desired top-level property:
[pscustomobject] #{ logins = $user_data } | ConvertTo-Json -Depth 10
As for what you tried:
If you use a preexisting JSON string as the value of property to be converted to JSON with ConvertTo-Json, it is treated like any other string value, resulting in the representation you saw, with " characters escaped as \" and (CRLF) newlines as \r\n
A simple example:
[pscustomobject] #{
foo = '{ "bar":
"baz" }'
} | ConvertTo-Json
Output (note how the foo property value became a single-line string with " and newlines escaped):
{
"foo": "{ \"bar\": \n \"baz\" }"
}
Ok, i spent way to much time on this.
Using jq, i want to test if an element exist in an array, if yes being able to mofify this element, if not adding this element to that array
I have read
Update one value in array of dicts, using jq
How to check if element exists in array with jq
Which gave hints But i am stuck
Let say i have a json file like :
{
"LOGIN":"user",
"COPY": [
{
"CHAINLIST":"chain1",
"ELEMENT": [ "element1-1","element1-2" ]
},
{
"CHAINLIST":"chain2",
"ELEMENT": [ "element2-1","element2-2" ]
}
]
}
I Would like to add elements to the COPY array based in the CHAINLIST id , let say those 3 elements :
//ELEM A
{
"CHAINLIST":"chain3",
"ELEMENT": [ "element3-1" ]
}
//ELEM B
{
"CHAINLIST":"chain2",
"ELEMENT": [ "element2-1","element2-3" ]
}
//ELEM C
{
"CHAINLIST":"chain1",
"ELEMENT": [ "element1-1","element1-2" ]
}
ELEM A has the CHAINLIST id chain3 who doesn't exit in the COPY Array _> let's add it
ELEM B Is already present in the COPY aray, I want to update the ELEMENT array
content with the new value
ELEM C Already exist and is up to date, i don't need to do anything.
In my example the final json object would be
{
"LOGIN":"user",
"COPY": [
{
"CHAINLIST":"chain1",
"ELEMENT": [ "element1-1","element1-2" ]
},
{
"CHAINLIST":"chain2",
"ELEMENT": [ "element2-1","element2-2","element2-3" ]
},
{
"CHAINLIST":"chain3",
"ELEMENT": [ "element3-1"]
}
]
}
I am using jq The procedure to add the element Elem to the object Obj would be :
Elem.CHAINLIST exist in Obj.COPY [] ?
yes : add Elem.ELEMENT to Obj.ELEMENT[] with unique to qvoid duplicates
no : add Elem to Obj.COPY[]
The best i get is
(if .COPY[]? | select (.CHAINLIST=="chain3") == "" then . else .COPY[.COPY | length ] |= . + { "CHAINLIST":"chain3","ELEMENT":[ "element3-1"]} end )
But select (.CHAINLIST=="chain3") == "" return nothing I i can figure out how to test if empty.
Thank you for your time !
The following solution uses the built-in function INDEX/2 to create convenient and efficient representations
of the collections of CHAINLIST-ELEMENT objects, together with a bespoke function, augment/1, for combining elements.
It is assumed that the objects defining the updates are presented as an array in the file edits.json.
< input.json jq --argfile edits edits.json '
# Use `unique` to combine the .ELEMENT fields
def augment($b):
reduce ($b|keys_unsorted[]) as $key (.;
.[$key].ELEMENT = (.[$key].ELEMENT + $b[$key].ELEMENT | unique));
(INDEX($edits[];.CHAINLIST) | map_values(del(.CHAINLIST))) as $edits
| (INDEX(.COPY[]; .CHAINLIST) | map_values(del(.CHAINLIST))) as $COPY
| .COPY |= ($COPY
| augment($edits)
| to_entries
| map( { CHAINLIST: .key, ELEMENT: .value.ELEMENT} ))
Output: as specified in the question.
Note: if the objects defining the updates are presented as a sequence of objects in a file, you could use the above solution with --slurpfile instead of --argfile.
I'm totally brand new to JSON and jq so this might seem like a simple question.
I'd like to change an array of numbers into an array of objects with a key for each value (number).
Let's say I have a JSON file like this:
{
"foo": [1519739200, 1519739600, 1519740000]
}
Then my desired output would be:
{
"foo": [
{
"id": 1519739200
},
{
"id": 1519739600
},
{
"id": 1519740000
},
]
}
So far everything I've seen was connected with adding new keys with values to existing object or merging two arrays into few objects. I know that I can add more keys into already existing object but how can I add keys to an array? I assume I have to change array elements into objects first but how do I do it?
Thank you for answer.
Check this,
https://jqplay.org/s/xF9DyVbhXD
{ foo : [ { id : .foo[] } ] }
There are a few ways to go about it.
First you want to create a new object for each item in foo:
$ jq -c '{ id: .foo[] }'
{"id":1519739200}
{"id":1519739600}
{"id":1519740000}
You can then rebuild the "shape" you had - first with [ ... ]
$ jq -c '[ { id: .foo[] } ]'
[{"id":1519739200},{"id":1519739600},{"id":1519740000}]
Then the { foo: }
$ jq -c '{ foo: [ { id: .foo[] } ] }'
{"foo":[{"id":1519739200},{"id":1519739600},{"id":1519740000}]}
Another option is to use |= to modify/update .foo directly.
$ jq -c '.foo |= [{id: .[]}]'
{"foo":[{"id":1519739200},{"id":1519739600},{"id":1519740000}]}
I'm trying to format some data that consists of json objects that includes some identifying information along with an array of one or more json objects, I would like the result to be one line of data per array element where each line should include some fields from the array element and some fields from the identifying information.
My sample data is below:
{
"eventCreation": {
"timeStamp": "2020-06-06T15:07:20Z",
"epoch": 1591456040
},
"eventData": {
"applName": "SampleApp",
"channelName": "SYSTEM.DEF.SVRCONN",
"connectionName": "127.0.0.1",
"channelType": "Svrconn",
"remoteProduct": "MQJM",
"remoteVersion": "09010005",
"activityTrace": [
{
"operationId": "Get",
"operationTime": "11:07:18",
"qmgrOpDuration": 102,
"reasonCode": {
"name": "No Msg Available",
"value": 2033
},
"objectName": "SYSTEM.DEFAULT.LOCAL.QUEUE"
},
{
"operationId": "Cb",
"operationTime": "11:07:18",
"qmgrOpDuration": 10,
"reasonCode": {
"name": "None",
"value": 0
},
"objectName": "SYSTEM.DEFAULT.LOCAL.QUEUE"
},
{
"operationId": "Cb",
"operationTime": "11:07:18",
"qmgrOpDuration": 12,
"reasonCode": {
"name": "None",
"value": 0
},
"objectName": "SYSTEM.DEFAULT.LOCAL.QUEUE"
}
]
}
}
I would like to get an output like this:
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","11:07:18","Get",102,"SYSTEM.DEFAULT.LOCAL.QUEUE",2033
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","11:07:18","Cb",10,"SYSTEM.DEFAULT.LOCAL.QUEUE",0
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","11:07:18","Cb",12,"SYSTEM.DEFAULT.LOCAL.QUEUE",0
I can pick any one element of the array and get it to print 3 lines, but if I add a 2nd element it will print 9 lines, 3rd element prints 27, etc.
For example:
jq -r '{channelName: .eventData.channelName, channelType: .eventData.channelType, connectionName: .eventData.connectionName, applName: .eventData.applName, remoteProduct: .eventData.remoteProduct, remoteVersion: .eventData.remoteVersion, operationId: .eventData.activityTrace[].operationId}|[.[]]|#csv' TEST.json
Will produce this:
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Get"
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Cb"
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Cb"
If I add a second like this:
jq -r '{channelName: .eventData.channelName, channelType: .eventData.channelType, connectionName: .eventData.connectionName, applName: .eventData.applName, remoteProduct: .eventData.remoteProduct, remoteVersion: .eventData.remoteVersion, operationId: .eventData.activityTrace[].operationId, qmgrOpDuration: .eventData.activityTrace[].qmgrOpDuration}|[.[]]|#csv' TEST.json
Will produce this:
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Get",102
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Get",10
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Get",12
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Cb",102
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Cb",10
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Cb",12
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Cb",102
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Cb",10
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Cb",12
Using your approach, the following is a solution:
.eventData
| ({channelName, channelType, connectionName, applName, remoteProduct, remoteVersion}
+ ( .activityTrace[]
| { operationTime, operationId, qmgrOpDuration, objectName, v: .reasonCode.value}))
| [.[]]
| #csv
The key is to iterate just once.
Notice also that this solution achieves its brevity in part by using the fact that {foo: .foo} can be abbreviated to {foo}.
A slightly more efficient approach
.eventData
| [.channelName, .channelType, .connectionName, .applName, .remoteProduct, .remoteVersion]
+ ( .activityTrace[]
| [.operationTime, .operationId, .qmgrOpDuration, .objectName, .reasonCode.value] )
| #csv
.operationTime first
.eventData
| [.channelName, .channelType, .connectionName, .applName, .remoteProduct, .remoteVersion] as $x
| ( .activityTrace[]
| [.operationTime]
+ $x
+ [.operationId, .qmgrOpDuration, .objectName, .reasonCode.value] )
| #csv
I have a JSON with the following content:
{
"data": [
{
"name": "Test",
"program": {
"publicAccess": "--------",
"externalAccess": false,
"userGroupAccesses": [
{
"access": "r-------"
},
{
"access": "rw------"
}
],
"id": "MmBqeMLIC2r"
},
"publicAccess": "rw------"
}
]
}
And I want to delete all keys (recursively) which match publicAccess or userGroupAccesses, so that my JSON looks like this:
{
"data": [
{
"name": "Test",
"program": {
"externalAccess": false,
"id": "MmBqeMLIC2r"
}
}
]
}
I've copied jq's builtin walk function from source.
# Apply f to composite entities recursively, and to atoms
def walk(f):
. as $in
| if type == "object" then
reduce keys[] as $key
( {}; . + { ($key): ($in[$key] | walk(f)) } ) | f
elif type == "array" then map( walk(f) ) | f
else f
end;
# My Code
walk(if (type == "object" and .publicAccess)
then del(.publicAccess)
elif (type == "array" and .userGroupAccesses)
then del(.userGroupAccesses)
else
.
end )
Gives me jq: error (at <stdin>:2622): Cannot index array with string "userGroupAccesses". Also if I use .userGroupAccesses[] - How do I get the result?
Snippet on jqplay: https://jqplay.org/s/1m7wAeHMTu
Your problem is when type == "array" is true . will be an array so .userGroupAccesses won't work. What you want to do is focus on the case when . is an object. In your call to walk you only need to check for type == "object" and then remove the members you don't want. e.g.
walk(if type == "object" then del(.publicAccess, .userGroupAccesses) else . end)
Try it online at jqplay.org
You can also solve this without walk by using Recursive Descent .. e.g.
del(.. | .publicAccess?, .userGroupAccesses?)
Try it online at jqplay.org