I have a file that contains objects with duplicate fields
[
{
"a": "random text",
"b": "more random text",
"c": "more random text",
"b": "something else",
"c": "more something else"
},
{
"a": "random text 2",
"b": "more random text 2",
"c": "more random text 2",
"b": "something else 2",
"c": "more something else 2"
}
]
Since I'm using javascript, when I try to print the data out, it only recognizes the last of the duplicate fields, i.e. I can only print b: something else, c: more something else, b: something else 2, c: more something else 2. I don't have control over the source of the file so I'm wondering if there is a way to handle this using javascript. Another option is using bash to change the second "b" and "c" into something like "b2" and "c2" but not all objects have "b" and "c". Any ideas would be highly appreciated, thank you!
Edit: fixed format of the file.
CodePudding user response:
With your problematic JSON as input:
echo Using jm
input | jm --pointer '/-' -s
echo Using jq
input | jq -n --stream '1|truncate_stream(inputs)|select(length>1)' | jq -c '{(.[0][0]): .[1]}'
produces:
Using jm
{"a": "random text"}
{"b": "more random text"}
{"c": "more random text"}
{"b": "something else"}
{"c": "more something else"}
{"a": "random text 2"}
{"b": "more random text 2"}
{"c": "more random text 2"}
{"b": "something else 2"}
{"c": "more something else 2"}
Using jq
{"a":"random text"}
{"b":"more random text"}
{"c":"more random text"}
{"b":"something else"}
{"c":"more something else"}
{"a":"random text 2"}
{"b":"more random text 2"}
{"c":"more random text 2"}
{"b":"something else 2"}
{"c":"more something else 2"}
You can take it from there.
Disclaimer: jm is a wrapper script I wrote for JSON Machine.
CodePudding user response:
The following is more complex but it does facilitate keeping the JSON objects in the input distinct:
jq -nc --stream 'foreach (1 | truncate_stream(inputs)) as $in ({};
.emit = null
| if $in|length <= 1
then .emit = .value | .value = null
else $in[0] as $p
| (.value|getpath($p)) as $v
| .value |= setpath($p; $v [$in[1]])
end ;
select(.emit).emit )
'
Output:
[{"a":["random text"],"b":["more random text","something else"],"c":["more random text","more something else"]}]
[{"a":["random text 2"],"b":["more random text 2","something else 2"],"c":["more random text 2","more something else 2"]}]
Warning: the above solution assumes that the input is an array of flat JSON objects, as in the Q. If the input does not take that form, the results will likely be unexpected.