3

JSON:

"{
  "a": "https://is2-ssl.com/",
  "b": "https://a5.-ssl.com/",
  "type": "response",
  "c": [
    {
      "Number": 1,
      "Reportname": "XXX",
      "size": "2.5",
      "Variants": [
        "YYY"
      ]
    }
  ],
"Meta": "ABC"
}

Required Output:

XXX,a,https://is2-ssl.com/
XXX,b,https://a5.-ssl.com/

I want to print those key value pairs in which the value contains "http"(url) and merge the key and value with delimiter "," and add ReportName to them

5
  • 1
    Hi! Welcome here. We're not really a free code-writing service. So, seeing you know that you should be using jq, please tell us where you're stuck – much easier to help you if you share your approach with us! Oct 9, 2022 at 16:37
  • i am completely new to json and jq. I tried using select, contains, with_entries but not able to print both key and value pair if value matche pattern
    – King
    Oct 9, 2022 at 16:38
  • Wow, well that's already pretty involved? Mind sharing (by editing your question) one of these approaches? I'm not too much of a jq-magician either, but I think with your help it's easy for the community to piece something together, even on a (traditionally slightly slow) Sunday evening. Oct 9, 2022 at 16:55
  • 1
    c appears to be an array. What should happen if there are several entries in that array? Is the initial double quote (which is unmatched) a typo? Are you showing the actual keys in the document? If not, it would be helpful if you could do that. It is unusual for a JSON structure to be this unorganised, so if you have a real document to share, that would be preferred. Extracting data by value (rather than by key) is also a bit unusual.
    – Kusalananda
    Oct 9, 2022 at 16:56
  • Can someone provide some site or book to master jq and json parsing. i read jq manual but still i cant handle complex parsing
    – King
    Oct 10, 2022 at 10:06

1 Answer 1

4

Assuming the initial " in the JSON document is a typo, that you want the .ReportName key's value from the first entry in the c array, and that you want the output as CSV:

$ jq -r '.c[0].Reportname as $n | map_values(select(type == "string" and startswith("http"))) | to_entries[] | [$n, .key, .value] | @csv' file
"XXX","a","https://is2-ssl.com/"
"XXX","b","https://a5.-ssl.com/"

The jq expression:

.c[0].Reportname as $n |
map_values(select(type == "string" and startswith("http"))) |
to_entries[] | [$n, .key, .value] | @csv

This first picks out the .Reportname value and assigns it to the internal jq variable $n. It then rewrites the original object by discarding any key not associated with a string starting with the substring http.

The example document is, after map_values() reduced to

{
  "a": "https://is2-ssl.com/",
  "b": "https://a5.-ssl.com/"
}

This is then converted with to_entries into the equivalent of

[
   { "key": "a", "value": "https://is2-ssl.com/" },
   { "key": "b", "value": "https://a5.-ssl.com/" }
]

... to get access to the keys themselves.

This array is expanded into a set of objects with [] and the saved value in $n together with the .key and .value part of each object in the set is used to create an array that is converted by @csv to quoted CSV output.


Another jq expression with the same output, but that does to_entries a bit earlier and then does map() on the created array rather than on the values of an object as we do with map_values() above.

.c[0].Reportname as $n | 
to_entries | 
map(
   select(.value | type == "string" and startswith("http")) |
   [$n, .key, .value] | @csv
)[]

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .