2

I am trying to merge two different JSON strings from STDIN (using pipe, not files) using jq command. Here's the command trying:

curl  ipinfo.io api.ipify.org/?format=json 2>/dev/null | jq -s

Output:

[
  {
    "ip": "139.162.244.103",
    "hostname": "businessproservices.com",
    "city": "London",
    "region": "England",
    "country": "GB",
    "loc": "51.5142,-0.0931",
    "postal": "EC2V",
    "org": "AS63949 Linode, LLC"
  },
  {
    "ip": "139.162.244.103"
  }
]

Expected output:

{
  "ip": "139.162.244.103",
  "hostname": "businessproservices.com",
  "city": "London",
  "region": "England",
  "country": "GB",
  "loc": "51.5142,-0.0931",
  "postal": "EC2V",
  "org": "AS63949 Linode, LLC"
}
1
  • curl ipinfo.io | jq will return expected output.
    – pLumo
    Apr 2, 2019 at 12:53

2 Answers 2

4

Your curl command queries two hosts. Each will return a JSON document. jq -s will add these together as two entries in an array. To get the first entry (which is what you're presenting as the expected output), simply request first (or .[0]) from jq, as in

curl -s ipinfo.io 'api.ipify.org/?format=json' | jq -s 'first'

or just use the first host from the start:

curl ipinfo.io

To actually merge the two document, apply the jq command add to the returned list:

curl -s ipinfo.io 'api.ipify.org/?format=json' | jq -s 'add'

Note that since a JSON object can't contain multiple keys with the same name, any later key will replace an equivalent earlier key, so that if your jq -s document is

[
  {
    "ip": "139.162.244.103",
    "hostname": "businessproservices.com",
    "city": "London",
    "region": "England",
    "country": "GB",
    "loc": "51.5142,-0.0931",
    "postal": "EC2V",
    "org": "AS63949 Linode, LLC"
  },
  {
    "ip": "39.62.44.1",
    "country": "UK"
  }
]

then this would be merged as

{
  "ip": "39.62.44.1",
  "hostname": "businessproservices.com",
  "city": "London",
  "region": "England",
  "country": "UK",
  "loc": "51.5142,-0.0931",
  "postal": "EC2V",
  "org": "AS63949 Linode, LLC"
}

when using jq -s add in place of jq -s.

4
  • Is this solution working for you? I had tried this but doesn't work for me, my jq version is jq-1.5-1-a5b5cbe
    – Pradeep
    Apr 2, 2019 at 13:20
  • @Pradeep With jq -s 'add'? Yes, it works for me using jq 1.6. I can't unfortunately test with an earlier version easily.
    – Kusalananda
    Apr 2, 2019 at 13:22
  • for me it works with jq 'add' (without -s option) Jul 12, 2021 at 22:16
  • @DirkHoffmann Yes, it would be enough if you passed the output of jq -s though jq add. This is the same as using jq -s add though.
    – Kusalananda
    Jul 13, 2021 at 20:24
-1
echo '
[
  {
    "ip": "139.162.244.103",
    "hostname": "businessproservices.com",
    "city": "London",
    "region": "England",
    "country": "GB",
    "loc": "51.5142,-0.0931",
    "postal": "EC2V",
    "org": "AS63949 Linode, LLC"
  },
  {
    "ip": "127.0.0.1",
    "country": "UK",
    "additional": "added Value"
  }
]' | jq  "add"

result

{
  "ip": "127.0.0.1",
  "hostname": "businessproservices.com",
  "city": "London",
  "region": "England",
  "country": "UK",
  "loc": "51.5142,-0.0931",
  "postal": "EC2V",
  "org": "AS63949 Linode, LLC",
  "additional": "added Value"
}```
1
  • Yes, if you're starting with what you get from curl URL1 URL2 | jq -s, then it will be enough with jq add. Note that the output of curl URL1 URL2 is a set of two JSON objects ({...} {...}), not an array of two objects ([{...},{...}]). The user is showing the output after passing the curl output through jq -s.
    – Kusalananda
    Jul 13, 2021 at 20:23

You must log in to answer this question.

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