I have following JSON
{
"ID": "123",
"Name": "xyz"
}
{
"ID": "1234",
"Competitor": "abc"
}
Need to convert the json objects into a array of json objects:
[
{
"ID": "123",
"Name": "xyz"
}
{
"ID": "1234",
"Competitor": "abc"
}
]
I have tried using:
. | [{ID, Name}]
But this converts into multiple arrays
[
{
"ID": "123",
"Name": "xyz"
}
]
[
{
"ID": "1234",
"Competitor": "abc"
}
]
jq applies the given filter to each JSON document/entity. A file can contain multiple such documents. If you want to handle a file with multiple documents as a single array document with each original document being an array element, then use -s/--slurp option which will read all JSON documents in your input file as one huge array:
jq -s '.' input.json
Output:
[
{
"ID": "123",
"Name": "xyz"
},
{
"ID": "1234",
"Competitor": "abc"
}
]
Note that jq requires valid JSON, so your input must be valid. The sample in the question is not. A valid JSON input would be:
{
"ID": "123",
"Name": "xyz"
}
{
"ID": "1234",
"Competitor": "abc"
}
PS Note that . | [{ID, Name}] is equivalent to [{ID, Name}] since . is the identity filter.
Related
I have the following JSON array
[
{
"login": "foo",
"id": 111
},
{
"login": "bar",
"id": 222
},
{
"login": "foobar",
"id": 333
}
]
How can I leverage the jq (preferrably) to check whether the object with "login": "bar" is member of this array?
Use any/1.
any(.login == "bar")
Online demo
I am new to jq and I'm trying to use it to search for a value in a json file based on a key that is located deep in the json structure. Here is a sample of my json file:
{
"data": {
"inventory": {
"location": "remote",
"list": {
"content": [
{
"item": {
"name": "minivan"
},
"owner": {
"id": "12345",
"state": "CA"
}
},
{
"item": {
"name": "sedan"
},
"owner": {
"id": "67890",
"state": "AZ"
}
}
]
}
}
}
}
An example of search that I'm trying to do is:
select item.name where owner.id = "67890"
and the expected output would be:
item.name = "sedan"
I'm trying to run the following:
jq '.[] | select .owner.id = "67890" | .item.name' json
and it generates an error:
jq: error: select/0 is not defined at <top-level>, line 1:
.[] | select .owner.id = "67890" | .item.name
jq: 1 compile error
Any pointers on how to do this in jq would be much appreciated!
Thanks!
First, you have to "navigate" to where you want to make the query. This seems to be an array.
.data.inventory.list.content
[
{
"item": {
"name": "minivan"
},
"owner": {
"id": "12345",
"state": "CA"
}
},
{
"item": {
"name": "sedan"
},
"owner": {
"id": "67890",
"state": "AZ"
}
}
]
Demo
Next, let's iterate over that array's items, which gives us a stream of objects.
.[]
{
"item": {
"name": "minivan"
},
"owner": {
"id": "12345",
"state": "CA"
}
}
{
"item": {
"name": "sedan"
},
"owner": {
"id": "67890",
"state": "AZ"
}
}
Demo
From these objects we select those that match your criteria.
select(.owner.id == "67890")
{
"item": {
"name": "sedan"
},
"owner": {
"id": "67890",
"state": "AZ"
}
}
Demo
Finally, we extract the value you're interested in.
.item.name
"sedan"
Demo
Everything combined in a jq call would be:
jq '.data.inventory.list.content[] | select(.owner.id == "67890").item.name'
"sedan"
Demo
This output is still valid JSON document (containing nothing but a JSON string). If you want to process the output as raw text, use the --raw-output (or -r) option:
jq -r '.data.inventory.list.content[] | select(.owner.id == "67890").item.name'
sedan
Demo
Here's a solution that avoids having to "navigate" to the right place, and which is also quite close to your SQL-like query:
..
| objects
| select(.owner and
(.owner|type=="object" and .id == "67890"))
.item.name
or more succinctly:
..|objects|select(.owner.id? == "67890").item.name
I'd like to select/identity-output all objects in arrays under "emp" keys into a flat array of those objects.
[
{
"eng": {
"dev": {
"dir": {
"name": "Mickey"
},
"emp": [
{
"name": "Goofy",
"job": "laugh",
"start": "today"
},
{
"name": "Minnie",
"job": "laugh"
}
]
}
}
},
{
"mgmt": {
"dir": {
"name": "Donald"
},
"emp": [
{
"name": "Woody",
"job": "smile"
},
{
"name": "Buzz",
"job": "smile"
}
]
}
}
]
I'm looking for a flat array of arbitrary objects found in arbitrary locations within the document (in this example, under "emp" parent/keys).
In this example, it would look like
[
{
"name": "Goofy",
"job": "laugh",
"start": "today"
},
{
"name": "Minnie",
"job": "laugh"
},
{
"name": "Woody",
"job": "smile"
},
{
"name": "Buzz",
"job": "smile"
}
]
I've looked through a lot of documentation and am able to do this if I know in advance precisely where these 'emp' keys are in the document, but not if they're distributed through the document at a priori unknown locations/paths.
Use recurse to walk the structure. From all the substrucures, select objects with the emp key. Output the corresponding values and merge the resulting arrays.
jq '[recurse | select (type == "object" and .emp) | .emp ] | add' file.json
Below is the JSON Output got for one of the API call, now need to get the date based on the name value, for example want to iterate the JSON file and look for name variable value which is equal to 1.0 then want to have date which is 2018-12-13T18:04:42-0500.
VERBOSE: {
"paging": {
"pageIndex": 1,
"pageSize": 100,
"total": 2
},
"analyses": [
{
"key": "xxxx",
"date": "2019-06-07T18:04:56-0400",
"events": [
{
"key": "xxxxxx",
"category": "VERSION",
"name": "01.00"
}
]
},
{
"key": "yyyyyy",
"date": "2018-12-13T18:04:42-0500",
"events": [
{
"key": "yyyyyy",
"category": "VERSION",
"name": "1.0"
}
]
}
]
}
Assuming you have the entire JSON text in a string variable, say $Json, would this work for you?
$obj = $Json | ConvertFrom-Json
$obj.analyses | ForEach-Object { if ($_.Events.Name -eq "1.0"){$_.Date}}
For example,
Input:
{
"id":"abc",
"name": "name-middlenane-lastname-1"
},
{
"id":"123",
"name": "fname-flast-2"
}
response:
{
"id":"abc",
"name": "name-middlename-lastname-1",
"newkey": "name-middlename-lastname"
},
{
"id":"123",
"name": "fname-flast-2",
"newkey": "fname-flast"
}
The filed name in each object is a string with characters and numbers separated by "-" hyphen. I need the complete string from beginning till the starting number. I don't want anything which is there after the number. And then the add new field with key as newkey and value should be extracted string without the number. Thus, the output should contain old fields as well as new one.
jq solution:
Sample input.json:
[
{
"id": "abc",
"name": "name-middlenane-lastname-1"
},
{
"id": "123",
"name": "fname-flast-2"
}
]
jq 'map(. + (.name | capture("(?<newkey>.+)-[0-9]+")) )' input.json
The output:
[
{
"id": "abc",
"name": "name-middlenane-lastname-1",
"newkey": "name-middlenane-lastname"
},
{
"id": "123",
"name": "fname-flast-2",
"newkey": "fname-flast"
}
]