How to JSON.stringify insert a file into a JSON message?

1.3k views Asked by At

I have a SNS JSON message here: https://s.natalian.org/2016-12-15/sns-event.json

However I need to use the Message field as a payload for a JSON data structure. How do I quickly get a piece of JSON inserted so the final JSON looks like: https://s.natalian.org/2016-12-15/sns-event-stringified-message.json

"Message": "[{\"From\": \"foo\",\"To\": \"bar\"}]",

For the sake of this example, file.json to be inserted has the contents:

[
  {
    "From": "foo",
    "To": "bar"
  }
]

I'm doing it by hand currently with JSON.stringify which error prone with a large structure.

2

There are 2 answers

0
Jeff Mercado On BEST ANSWER

Read the other file in as an argument file, then assign the new message value from the file. You can obtain a stringified version of the current object using tojson (or @json).

$ jq --argfile file file.json '.Records[0].Sns.Message = ($file | tojson)' input.json
0
peak On

Here's a slightly different approach that is also more general.

Suppose we want to assign a value to the "Message" field, wherever it occurs (and no matter how often it occurs), without having to worry about the details.

To do this with complete generality, here's a function that takes a field name (a JSON string) and the desired value:

def setall(key; value):
  walk(if type == "object" and has(key) then .[key] = value else . end);

(In case your jq does not have walk/1, its definition, as given in jq's builtin.jq, is included below.)

To solve the original problem, the filter to use would be:

setall( "Message"; $file|tojson )

where $file can be defined on the command line as follows:

$ jq --argfile file file.json -f setall.jq input.json

Here it has been assumed that all the jq bits have been placed in a file named setall.jq.

walk/1

# 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;