0

I have a Main json file.

{
  "swagger": "2.0",
    "paths": {
    "/agents/delta": {
      "get": {
        "description": "lorem ipsum doram",
        "operationId": "getagentdelta",
        "summary": "GetAgentDelta",
        "tags": [
          "Agents"
        ],
        "parameters": [
          {
            "name": "since",
            "in": "query",
            "description": "Format - date-time (as date-time in RFC3339). The time from which you need changes from. You should use the format emitted by Date's toJSON method (for example, 2017-04-23T18:25:43.511Z). If a timestamp older than a week is passed, a business rule violation will be thrown which will require the client to change the from date. As a best-practice, for a subsequent call to this method, send the timestamp when you <b>started</b> the previous delta call (instead of when you completed processing the response or the max of the lastUpdateOn timestamps of the returned records). This will ensure that you do not miss any changes that occurred while you are processing the response from this method",
            "required": true,
            "type": "string"
          }
        ]
        }
        }
        }
        }

And I have a smaller json file.

{ 
                                                                  "name": "Authorization",
                  "description": "This parameter represents the Authorization token obtained from the OKTA Authorization server. It is the Bearer token provided to authorize the consumer. Usage Authorization : Bearer token",
                  "in": "header",
                  "required": true,
                  "type": "string"
               }

Now I need to add the contents of the smaller json file into the Main.Json file in the parameters array.

I tried the below command

cat test.json | jq --argfile sub Sub.json '.paths./agents/delta.get.parameters[ ] += $sub.{}' > test1.json

But I get the below error:

jq: error: syntax error, unexpected '{', expecting FORMAT or QQSTRING_START (Unix shell quoting issues?) at <top-level>, line 1:
.paths += $sub.{}               
jq: 1 compile error
cat: write error: Broken pipe

I tried this command.

cat test.json | jq '.paths./agents/delta.get.parameters[ ] | = (.+ [{ "name": "Authorization", "description": "This parameter represents the Authorization token obtained from the OKTA Authorization server. It is the Bearer token provided to authorize the consumer. Usage Authorization : Bearer token", "in": "header",  "required": true,  "type": "string" }] )' > test1.json

And I get no error and no output either. How do I get around this? I would have to add the contents of the smaller json file directly first. And then at a later stage, search if it already had name: Authorization and it's other parameters, and then remove and replace the whole name: Authorization piece with the actual contents of the smaller.json, under each path that starts with '/xx/yyy'.

Edited to add: For the last part of the question, I could not use the walk function, since I have jq 1.5 and since am using the bash task within Azure DevOps, I can't update the jq installation file with the walk function. Meanwhile I found the use of something similar to wildcard in jq, and was wondering why I can't use it in this way.

jq --slurpfile newval auth.json '.paths | .. | objects | .get.parameters += $newval' test.json > test1.json

Can anyone please point out the issue in the above command? It did not work, and am not sure why..

AK123
  • 365
  • 6
  • 17
  • That doesn't look even *remotely* like valid `jq` syntax. Where did you get the `#.` from? What's with the backslash literals? – Charles Duffy Aug 19 '19 at 02:52
  • Also, the data isn't valid JSON as-given, so we can't test with it (there are commas in places they aren't allowed). – Charles Duffy Aug 19 '19 at 02:54
  • Am sorry. It was a longer json file that I edited to put here. I will edit the question now. And on the `#.` I was trying to access the /agents/delta and I found a link using css , which i tried to apply here, as I could find ways around a backslash but not a forward slash. Link - https://stackoverflow.com/questions/5153986/css-selector-to-select-an-id-with-a-slash-in-the-id-name – AK123 Aug 19 '19 at 03:06
  • @AK123 - The link you've provided references CSS selectors, which really have nothing to do with jq. The confusion about CSS probably explains some of the downvotes for this Q. Maybe it would help if you revised the question so it doesn't evince any confusion. – peak Aug 19 '19 at 05:05
  • @peak Thank you. I agree. I shall edit the question and remove the `#.` references that seems to be confusing. – AK123 Aug 19 '19 at 05:32

1 Answers1

4

You want --slurpfile, and you need to escape /agents/delta part of the path with quotes:

$ jq --slurpfile newval insert.json '.paths."/agents/delta".get.parameters += $newval' main.json
{
  "swagger": "2.0",
  "paths": {
    "/agents/delta": {
      "get": {
        "description": "lorem ipsum doram",
        "operationId": "getagentdelta",
        "summary": "GetAgentDelta",
        "tags": [
          "Agents"
        ],
        "parameters": [
          {
            "name": "since",
            "in": "query",
            "description": "Format - date-time (as date-time in RFC3339). The time from which you need changes from. You should use the format emitted by Date's toJSON method (for example, 2017-04-23T18:25:43.511Z). If a timestamp older than a week is passed, a business rule violation will be thrown which will require the client to change the from date. As a best-practice, for a subsequent call to this method, send the timestamp when you <b>started</b> the previous delta call (instead of when you completed processing the response or the max of the lastUpdateOn timestamps of the returned records). This will ensure that you do not miss any changes that occurred while you are processing the response from this method",
            "required": true,
            "type": "string"
          },
          {
            "name": "Authorization",
            "description": "This parameter represents the Authorization token obtained from the OKTA Authorization server. It is the Bearer token provided to authorize the consumer. Usage Authorization : Bearer token",
            "in": "header",
            "required": true,
            "type": "string"
          }
        ]
      }
    }
  }
}

And here's one that first removes any existing Authorization objects from the parameters before inserting the new one into every parameters array, and doesn't depend on an the exact path:

jq --slurpfile newval add.json '.paths |= walk(
  if type == "object" and has("parameters") then
     .parameters |= map(select(.name != "Authorization")) + $newval
  else
     .
  end)' main.json
Shawn
  • 47,241
  • 3
  • 26
  • 60
  • Thank you so much. That worked! I guess `--slurpfile` can only be used to add json arrays? In case there is a need to just add a json object , is my understanding correct, to assume that i can use --slurp with an json argument passing that whole object into the variable and add it? i.e `jq --argjson newjson "{ "name": "AK123", "location": "XXX"}"` main.json – AK123 Aug 19 '19 at 07:04
  • I have jq 1.5, is there a way around using the map function for replacing all the Authorization objects and replacing them? – AK123 Aug 19 '19 at 10:49
  • @AK123 no idea; I've only ever used 1.6. – Shawn Aug 19 '19 at 16:00
  • Could you please let me know if by using objects I can still achieve the same . `jq --slurpfile newval auth.json '.paths | .. | objects | .get.parameters += $newval' test.json > test1.json` – AK123 Aug 22 '19 at 09:23