How to bring outer values inside an array iteration - json

I have a JSON in the shape
[
{
a:1,
b: [2,3]
},
{
a:4,
b: [5,6]
}
]
That I want to transform in the shape
[
[
{
a: 1,
b: 2,
},
{
a: 1,
b: 3,
},
],
[
{
a: 4,
b: 5,
},
{
a: 4,
b: 6,
},
],
]
That is I want to bring the value of the field a inside the array.
how can I do this with jq?

Try this :
jq 'map([{a,b:.b[]}])'
As #pmf pointed out, you can also update object :
jq 'map([.b=.b[]])'

You could iterate over the items using variable binding with as.
Then either update .b to have the value of its items using the update operator |=:
jq 'map([.b[] as $b | .b |= $b])'
Demo
Or create completely new objects from data collected:
jq 'map(.a as $a | [.b[] as $b | {$a,$b}])'
Demo
[
[
{
"a": 1,
"b": 2
},
{
"a": 1,
"b": 3
}
],
[
{
"a": 4,
"b": 5
},
{
"a": 4,
"b": 6
}
]
]

Related

jq: how to change structure of JSON avoiding cartesian product?

I have thin JSON input:
[
{
"x": [
"2020-02-24T00:00:00",
"2020-02-25T00:00:00",
"2020-02-26T00:00:00"
],
"y": [
3,
2,
6
]
}
]
And I would like to obtain:
[
{
"a": "2020-02-24T00:00:00",
"b": 3
},
{
"a": "2020-02-25T00:00:00",
"b": 2
},
{
"a": "2020-02-26T00:00:00",
"b": 6
}
]
If I apply .[]|{a:.x[],b:.y[]} I obtain the cartesian product (9 items).
How to change the structure of this JSON avoiding cartesian product?
Introducing a single "$-variable" keeps things brief and straightforward:
map(range(0; .x|length) as $i
| {a: .x[$i], b: .y[$i]})
but a $-variable free solution only requires one more line:
map([.x, .y]
| transpose[]
| {a: .[0], b: .[1]})

Using jq to merge two arrays into one array of objects

I am very beginner into jq and I want to reshape my JSON file.
I have ve got JSON structured like this:
{
"a": [1, 2, 3, 4 ...],
"b": [
{
"x": 1000,
"value": 1
},
{
"x": 1000,
"value": 2
},
{
"x": 1000,
"value": 3
}
...
]
}
I am wondering how I can achieve result like this with jq:
[
{
"value": 1,
"from": "a",
},
{
"value": 2,
"from": "a"
},
...
{
"value": 1,
"from": "b"
},
{
"value": 2,
"from": "b"
}
...
]
Here is a very slightly generic, but hardly robust, solution:
map_values( if type == "array"
then map(if type == "object" then .value else . end)
else . end)
| [ keys_unsorted[] as $k
| .[$k][] as $v
| { value: $v, from: $k } ]
Create two lists, one from .a and one from .b, and merge them with +.
In the first list, create objects with value: set to the original content and add from: "a"; in the second list, remove .x from elements of .b and add the from again.
jq '[.a[] | {value:(.), from: "a"}] + [.b[] | del(.x) + {from: "b"}]

How to "number" array items? [duplicate]

This question already has answers here:
How do i add an index in jq
(3 answers)
Closed 2 years ago.
Considering input:
[
{
"a": 1
},
{
"a": 2
},
{
"a": 7
}
]
how do I add new field to each object, which value would be index in array? Producing:
[
{
"a": 1,
"index": 0
},
{
"a": 2,
"index": 1
},
{
"a": 7,
"index": 2
}
]
Using reduce, without disassembling/reassembling the input:
reduce range(length) as $index (.; .[$index] += {$index})
Online demo
Store the structure into a variable, then use keys to get the indices, retrieve the corresponding object from the variable using the index and add the index to it:
jq '[ . as $d | keys[] | $d[.] + {index:.} ]' file.json
to_entries takes an object and returns an array of key/value pairs.
It can be used effectively and intuitively.
jq/to_entries
input file
// file.json
[
{
"a": 1
},
{
"a": 2
},
{
"a": 7
}
]
commands
jq 'to_entries | map(.value+{index:.key})' file.json
results
[
{
"a": 1,
"index": 0
},
{
"a": 2,
"index": 1
},
{
"a": 7,
"index": 2
}
]
Here's also an alternative (non-jq) solution, using jtc:
bash $ <input.json jtc -w'[:]<I>k' -i'{"index":{I}}'
[
{
"a": 1,
"index": 0
},
{
"a": 2,
"index": 1
},
{
"a": 7,
"index": 2
}
]
bash $
PS. I'm a developer of jtc - unix JSON processor
PPS. The disclaimer is required by SO.
Try : Array[index_of_object].property = value
for example : array[0].a = 1

Conditional deletion from array of field A with condition on field B

Let's say I have a json with an array inside. Say that the elements of this array are objects with keys A and B. I would like to remove the B objects on the elements where A objects meet a certain condition.
For example, I would like to remove the B objects where A is greater than 5, transforming
{
"title": "myTitle",
"myArray": [
{
"A": 1,
"B": "foo"
},
{
"A": 4,
"B": "bar"
},
{
"A": 7,
"B": "barfoo"
},
{
"A": 9,
"B": "foobar"
}
]
}
into
{
"title": "myTitle",
"myArray": [
{
"A": 1,
"B": "foo"
},
{
"A": 4,
"B": "bar"
},
{
"A": 7
},
{
"A": 9
}
]
}
The task seems easy enough and if I had't have to keep the A's it would be a simple del(select..) thing. There surely must be an elegant way to do this as well?
Thank you!
You can still use a del(select..) thing.
.myArray[] |= del(select(.A > 5) .B)
demo at jqplay.org

Reshape a jq array with summarized data

New to jq but I've managed to group a load of data which I would now like summarized in a different format. Original data after group by and mapping:
[
{
"Agents": "a",
"Count": 1
},
{
"Agents": "b",
"Count": 50
},
{
"Agents": "c",
"Count": 25
},
{
"Agents": "d",
"Count": 1
},
{
"Agents": "e",
"Count": 4
},
{
"Agents": "f",
"Count": 4
},
{
"Agents": "g",
"Count": 4
}
]
and I would like this output:
{
"Count": 7,
"Agents": {
"a": 1,
"b": 50,
"c": 25,
"d": 1,
"e": 4,
"f": 4,
"g": 4
}
}
How exactly might I do this in jq please because it requires mapping the values as field names?
Another variant using reduce would be to do. The reduce expression takes the array as input and puts the key as the Agents and the value as its corresponding Count value.
jq '{ Count: length, Agents: (reduce .[] as $d ({}; .[$d.Agents] = $d.Count)) }'
The Object Value Iterator .[] used to construct the JSON. For a given .["a"], it returns "a" which is how the keys are constructed in the final JSON.
Use map to create an input for from_entries:
map({key: .Agents, value: .Count}) | {Count: length, Agents: from_entries}
map produces a list of objects like [{"key": "a", "value": 1}, ...]. from_entries turns that into a single object {"a": 1, ...}. In the final object, both length and from_entries get the same array as input, and their outputs are used to create the final object with Count and Agents keys.