jsonbatch-filejqtext-parsing

parsing a JSON containing several stringified jsons using Batch and JQ


I am creating an integration between two websites my company uses to track data. The API for one of the sites (Monday.com) has returned a json with several smaller json values stored as strings inside of it. I am having trouble parsing these values without calling fromjson individually on every single value.

The json I am receiving is formatted like:

[
  {
    "name": "xxxxxxxxxxx",
    "percentage": "\"80\"",
    "Status": "{\"index\":1,\"post_id\":null,\"changed_at\":\"2019-07-29T14:44:50.305Z\"}",
    "Timeline": "{\"from\":\"2019-07-03\",\"to\":\"2019-07-25\",\"changed_at\":\"2019-07-29T14:55:39.487Z\"}",
    "Interview Done": "{\"date\":\"2019-07-03\",\"changed_at\":\"2019-07-23T19:56:01.004Z\"}",
    "Credentials Done": "{\"date\":\"2019-07-02\",\"changed_at\":\"2019-07-23T19:57:39.021Z\"}",
    "Skills Done": "{\"date\":\"2019-07-24\",\"changed_at\":\"2019-07-23T19:55:10.847Z\"}",
    "orientation Date": "{\"date\":\"2019-07-25\",\"changed_at\":\"2019-07-23T19:55:07.670Z\"}",
    "Hire Date": null
  },
  {
    "name": "yyyyyyyyyyyy",
    "percentage": null,
    "Status": "{\"index\":1,\"post_id\":null,\"changed_at\":\"2019-07-26T22:57:31.250Z\"}",
    "Timeline": "{\"from\":\"2019-07-17\",\"to\":\"2019-07-26\",\"changed_at\":\"2019-07-23T20:13:58.253Z\"}",
    "Interview Done": "{\"date\":\"2019-07-17\",\"changed_at\":\"2019-07-23T20:13:03.218Z\"}",
    "Credentials Done": "{\"date\":\"2019-07-24\",\"changed_at\":\"2019-07-25T16:12:40.484Z\"}",
    "Skills Done": "{\"date\":\"2019-07-17\",\"changed_at\":\"2019-07-23T20:13:29.884Z\"}",
    "orientation Date": "{\"date\":\"2019-07-25\",\"changed_at\":\"2019-07-23T20:11:52.848Z\"}",
    "Hire Date": null
  }
]

Is there a way to use a combination of Batch and jq in order to properly format this JSON as one large nested json, rather than a json containing several string formatted jsons?

I am struggling to parse the json dynamically as part of a batch script which fetches the json first, and then processes it before posting it to another API.

I have successfully parsed each thing individually using singular jq commands such as myjson.json | jq . | jq .[].Timeline fromjson


Solution

  • The simplest in your case would be to use walk/1:

    walk( if type == "string" then fromjson? // . else . end)
    
    

    More generally ...

    Sometimes it happens that applying fromjson just once is not enough. In such cases, the following should be sufficient as it will cause the above procedure to be applied until quiescence:

    def until_quiescence(f):
      (f as $x | if ($x == .) then . else ($x | until_quiescence(f)) end);
    
    until_quiescence(walk( if type == "string" then fromjson? // . else . end) )
    
    

    walk/1

    If your jq does not already have walk, simply include its def, which you can readily find e.g. by googling: jq "def walk"