EN VI

Json - How to substract inner array value from outer array value?

2024-03-15 23:30:05
Json - How to substract inner array value from outer array value?

I have the following test.json file:

{
    "now": 1685613599.879,
    "messages": 1347296469,
    "aircraft": [
      {
        "hex": "7c806e",
        "type": "adsc",
        "flight": "QF94    ",
        "r": "VH-ZNK",
        "t": "B789",
        "alt_baro": 34000,
        "gs": 475.0,
        "track": 231.55,
        "lat": 12.694702,
        "lon": -146.525860,
        "nic": 0,
        "rc": 0,
        "seen_pos": 24.752,
        "alert": 0,
        "spi": 0,
        "mlat": [],
        "tisb": [],
        "messages": 6145890,
        "seen": 24.8,
        "rssi": -49.5
      },
      {
        "hex": "3c4dc5",
        "type": "adsb_icao",
        "flight": "DLH9LL  ",
        "r": "D-ACNE",
        "t": "CRJ9",
        "alt_baro": 5250,
        "gs": 253.3,
        "track": 182.72,
        "lat": 49.848068,
        "lon": 7.385010,
        "nic": 8,
        "rc": 186,
        "seen_pos": 0.180,
        "alert": 0,
        "spi": 0,
        "mlat": [],
        "tisb": [],
        "messages": 9278490,
        "seen": 0.2,
        "rssi": -9.7
      }
    ]
  }
  

I'm matching certain aircraft with several select statements:

jq -r '.aircraft[] | [.lon, .lat, .alt_baro, .seen_pos, .hex ] | select(.[0] > 7) | select(.[0] < 10) | select(.[1] > 49) | select(.[1] < 51) | select(.[2] != null) | select(.[2] != "ground") | select(.[2] < 13000) | @csv' test.json

This part works fine (matches the second aircraft from the example above):

7.385010,49.848068,5250,0.180,"3c4dc5"

Now my problem: I'm struggling with doing some math on the fly. I want to subtract seen_pos from now and use that value in the result. My result should look like

7.385010,49.848068,5250,1685613599.699,"3c4dc5"

I can't figure out how to access now from the outer array. Would you kindly nudge me in the right direction?

Solution:

You'll need to remember .now before looping ([]) deeper.

Start your filter with .now as $now | ...

Then in the array you create to keep some data, you can use $now as needed:

.now as $now 
    | .aircraft[] 
    | [.lon, .lat, .alt_baro, .seen_pos, .hex, ($now - .seen_pos) ] 
    | select(.[0] > 7) | select(.[0] < 10) | select(.[1] > 49) | select(.[1] < 51) | select(.[2] != null) | select(.[2] != "ground") | select(.[2] < 13000) 
    | @csv

Output:

7.385010,49.848068,5250,0.180,"3c4dc5",1685613599.699

As you can test in this online JqPlay Demo.


An additional tip, consider using select() on the object itself, you're now creating a new array even tho select will ignore that object, something like this will prevent creating new arrays when it's not needed and stuff like .lon < 7 is a lot more readable then .[0] < 7.

.now as $now 
    | .aircraft[] 
    | select(.lon > 7 or .lat < 10)
    | [.lon, .lat, .alt_baro, .seen_pos, .hex, ($now - .seen_pos) ] 
    | @csv
Answer

Login


Forgot Your Password?

Create Account


Lost your password? Please enter your email address. You will receive a link to create a new password.

Reset Password

Back to login