jq: mapping json objects to another format schema - json

I need to transform an array of this kind of elements:
[
{
"Field1": "value1",
"Field2": "value2"
},
{
"Field1": "value3",
"Field2": "value4"
},
...
]
To:
[
"PutRequest": {
"Item": {
"Field1": {
"S": "value1"
},
"Field2": {
"S": "value2"
}
}
},
"PutRequest": {
"Item": {
"Field1": {
"S": "value3"
},
"Field2": {
"S": "value4"
}
}
},
...
]
I was thinking about using jq, but I don't quite figure out how to get it.
EDIT
Up to now, I've been able to get that:
[.[] | {"Field1": {"S": .Field1}, "Field2": {"S": .Field2}}]
Is there any what to say: for each field add an like key: {"S": .value}?
EDIT 2
Using map({PutRequest: {Item: map_values({S: .})}}) approach, it's generating me:
{
"S": {
"Field1": "value1",
"Field2": "value2",
}
}
I need:
"Item": {
"Field1": {
"S": "value3"
},
"Field2": {
"S": "value4"
}
}
Any ideas?

Does not exactly match your expected output but you're probably looking for something like this:
map({PutRequest: {Item: map_values({S: .})}})
Demo

Related

How to JSONify a subdocument in a MongoDB aggregation pipeline

I have a collection containing documents with JSON subdocuments
{
"field1": {"some_keys_a":42},
"field2": {"some_keys_b":42},
"field3": {"some_keys_c":42},
"fieldN": "..."
}
In a aggregation pipeline I need to serialize some of the fields in a string; at first I believed that there ought to be a $json operator I could call like:
{
"$set": {
"serialied_subdocument": {
"$toJson": {
"field1": "$field1",
"field2": "$field2",
"field3": "$field3",
}
}
}
}
My problem is that it does not look like such an operator exists. Is there another way to convert a subdocument or an array to a JSON string inside a pipeline?
I am using MongoDB 4.4 on Atlas.
For context I was previously using a pipeline with $group with does not require this stringification:
[
// Omitted $match and other stuff
{
"$project": {
"field1": true,
"field2": true,
"field3": true
}
},
{
"$group": {
"_id": {
"field1": "$field1",
"field2": "$field2",
"field3": "$field3"
}
}
},
{
"$replaceRoot": {
"newRoot": "$_id"
}
}
]
but lately the collection has significantly grown in size so I would like to use $merge
[
// Omitted $match and other stuff
{
"$project": {
"field1": true,
"field2": true,
"field3": true
}
},
{
"$set": {
"_id": {
"field1": "$field1",
"field2": "$field2",
"field3": "$field3"
},
"lookup_keys_for_later":"random_string_created_by_the_app_to_fetch_the_results"
}
},
{
"$merge": {
"into": "unique_field1_field2_field3",
"on": "_id",
"whenMatched": "keepExisting",
"whenNotMatched": "insert"
}
}
]
after which I would simply fetch the result by the "lookup_keys_for_later" key. The issue is that for $merge the _id needs to be a primitive.

jq: Include the lookup key as a field in the result value

I have a JSON object of the following form:
{
"vars": {
"node1": {"field1": "a", "field2": "b"},
"node2": {"field1": "x", "field2": "y"}
"unrelated": {"blah": "blah"}
},
"nodes": ["node1", "node2"]
}
Now, I can get the fields per node (excluding unrelated) using the following jq expression:
.vars[.nodes[]]
Output:
{
"field1": "a",
"field2": "b"
}
{
"field1": "x",
"field2": "y"
}
My question is, how do I include the vars key as a field in the output, i.e.
{
"node": "node1",
"field1": "a",
"field2": "b"
}
{
"node": "node2",
"field1": "x",
"field2": "y"
}
The name of the key (node in the example) is not important.
Based on this post I found an approximate solution:
.vars | to_entries | map_values(.value + {node: .key})[]
which outputs
{
"field1": "a",
"field2": "b",
"node": "node1"
}
{
"field1": "x",
"field2": "y",
"node": "node2"
}
{
"blah": "blah",
"node": "unrelated"
}
But it still includes the unrelated field which is shouldn't.
Store the nodes array's elements in a variable for reference. Storing the elements rather than the whole array automatically also iterates for the next step. Then, just compose your desired output objects using the nodes array item as object {$node} added to the looked-up object in .vars[$node].
jq '.nodes[] as $node | {$node} + .vars[$node]'
{
"node": "node1",
"field1": "a",
"field2": "b"
}
{
"node": "node2",
"field1": "x",
"field2": "y"
}
Demo

Jsonassert ignore key

There are 2 Json strings to compare.
1
"values": {
"-1487778947": {
"field1": "xxx",
"field2": "yyy",
"field3": {
"zzz": {
"field4": 21,
"field5": 28
}
}
},
"-1820451085": {
"field1": "fgf",
"field2": "dfd",
"field3": {
"zzz": {
"field4": 56,
"field5": 78
}
}
},
}
2
"values": {
"343434-35454-232467498": { // ignore this value
"field1": "xxx", // compare these fields
"field2": "yyy", // compare these fields
"field3": { // compare these fields
"zzz": { // compare these fields
"field4": 21, // compare these fields
"field5": 28 // compare these fields
}
}
},
"486787-4546-787344353": { // ignore this value
"field1": "fgf", // compare these fields
"field2": "dfd", // compare these fields
"field3": { // compare these fields
"zzz": { // compare these fields
"field4": 56, // compare these fields
"field5": 78 // compare these fields
}
}
},
}
I want to ignore the key of these objects and just match the inside fields. Is this possible with JsonAssert or any other library?
We can ignore the fields using customization. But not found a way to ignore only the object key and validate the child values.
With Jayway-JSONPath you can get only the child nodes from both JSON, thus ignoring the key.
INPUT JSON
{
"values": {
"-1487778947": {
"field1": "xxx",
"field2": "yyy",
"field3": {
"zzz": {
"field4": 21,
"field5": 28
}
}
},
"-1820451085": {
"field1": "fgf",
"field2": "dfd",
"field3": {
"zzz": {
"field4": 56,
"field5": 78
}
}
}
}
}
JSONPath
$.values.[*]
Output
[
{
"field1" : "xxx",
"field2" : "yyy",
"field3" : {
"zzz" : {
"field4" : 21,
"field5" : 28
}
}
},
{
"field1" : "fgf",
"field2" : "dfd",
"field3" : {
"zzz" : {
"field4" : 56,
"field5" : 78
}
}
}
]
Online Test Tool :
JSONLint - The JSON Validator
Jayway JsonPath Evaluator

Jolt - How to convert two arrays to key value and keep other singles properties

I have a JSON that contains two arrays that I need to convert to key / value pairs. These keys on the array are dynamic and can change.
For that I'm trying to create a Jolt spec to convert my input data into the format below.
JSON Input:
{
"data": [
{
"property1": "AA",
"property2": "BB",
"keys": [
"key1",
"key2",
"key3"
],
"values": [
"value1",
"value2",
"value3"
]
},
{
"property1": "CC",
"property2": "DD",
"keys": [
"key4",
"key5"
],
"values": [
"value4",
"value5"
]
}
]
}
Desired output:
[
{
"property1": "AA",
"property2": "BB",
"key1": "value1",
"key2": "value2",
"key3": "value3"
},
{
"property1": "CC",
"property2": "DD",
"key4": "value4",
"key5": "value5"
}
]
My spec:
[
{
"operation": "shift",
"spec": {
"data": {
"*": {
"values": {
"*": {
"#": "[&3].#(3,keys[&1])"
}
}
}
}
}
}
]
My spec output:
[
{
"key1": "value1",
"key2": "value2",
"key3": "value3"
},
{
"key4": "value4",
"key5": "value5"
}
]
But I'm not able to correctly include the simple properties (property1 and property2) as in the desired output.
Thanks in advance
[
{
"operation": "shift",
"spec": {
"data": {
"*": {
"property1": "[&1].property1",
"property2": "[&1].property2",
"values": {
"*": {
"#": "[&3].#(3,keys[&1])"
}
}
}
}
}
}
]
Really you grouped the dynamic elements into key-value pairs greatly, but you just missed the position mapping of property1 and property2 fields into output.

Querying complete JSON object using elasticsearch

I want to query for the complete Json.
I have Json objects saved in in different documents.
_id: 1,
my_json: {
"field1": "1",
"field2": "2",
"field3": "3",
"field4": "4"
}
_id: 2,
my_json: {
"field1": "11",
"field2": "22",
"field3": "33",
"field4": "44"
}
In my query I want to match for the complete combination not the single field. So I tried the query below but it is returning empty response.
{
"query": {
"bool": {
"must": [
{
"terms": {
"my_json": [
{
"field1": "11",
"field2": "22",
"field3": "33",
"field4": "44"
},
{
"field1": "1",
"field2": "2",
"field3": "3",
"field4": "4"
}
]
}
}
]
}
}
}
I need to work with more and more Json objects like above. So I cannot use the regular query.Hence I tried to match the complte the JSON object.
If you want to match all properties of a JSON object, you can do so but using one term query per field in your JSON, i.e. each field of your JSON must match
{
"query": {
"bool": {
"must": [
{
"term": {
"my_json.field1": "11"
}
},
{
"term": {
"my_json.field2": "22"
}
},
{
"term": {
"my_json.field3": "33"
}
},
{
"term": {
"my_json.field4": "44"
}
}
]
}
}
}