Drill 04: Conditions & Error Handling

if/then/else, the // operator, try/catch, and null handling patterns.

Run This Drill

bash ~/atelier/_bibliotheca/domus-captures/docs/modules/ROOT/examples/jq-drills/04-conditions.sh

Drill Script

#!/bin/bash
# JQ DRILL 04: CONDITIONS & ERROR HANDLING
# Paste this entire script into your terminal
# Topics: if/then/else, alternative operator, try/catch, null handling

cat << 'EOF' > /tmp/jq-04.json
{
  "endpoints": [
    {"name": "ise-01", "status": "up", "latency": 45, "errors": null},
    {"name": "ise-02", "status": "up", "latency": 120, "errors": null},
    {"name": "vault-01", "status": "down", "latency": null, "errors": "connection refused"},
    {"name": "bind-01", "status": "up", "latency": 5},
    {"name": "k3s-01", "status": "degraded", "latency": 250, "errors": "high load"}
  ],
  "thresholds": {
    "latency_warn": 100,
    "latency_crit": 200
  }
}
EOF

echo "=================================================================="
echo "             JQ DRILL 04: CONDITIONS & ERROR HANDLING            "
echo "=================================================================="
echo ""
echo "Test file: /tmp/jq-04.json"
echo ""

# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 4.1: IF/THEN/ELSE"
echo "Conditional logic in jq"
echo "------------------------------------------------------------------"
echo ""
echo "Command: jq '.endpoints[] | if .status == \"up\" then .name else empty end' /tmp/jq-04.json"
jq '.endpoints[] | if .status == "up" then .name else empty end' /tmp/jq-04.json
echo ""
echo "Command: jq '.endpoints[] | {name, health: (if .status == \"up\" then \"OK\" else \"FAIL\" end)}' /tmp/jq-04.json"
jq '.endpoints[] | {name, health: (if .status == "up" then "OK" else "FAIL" end)}' /tmp/jq-04.json
echo ""

# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 4.2: NESTED CONDITIONS"
echo "Multiple conditions with elif pattern"
echo "------------------------------------------------------------------"
echo ""
echo "Command:"
echo 'jq '"'"'.endpoints[] | {name, severity: (
  if .status == "down" then "CRITICAL"
  elif .status == "degraded" then "WARNING"
  else "OK" end
)}'"'"' /tmp/jq-04.json'
jq '.endpoints[] | {name, severity: (if .status == "down" then "CRITICAL" elif .status == "degraded" then "WARNING" else "OK" end)}' /tmp/jq-04.json
echo ""

# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 4.3: ALTERNATIVE OPERATOR (//)"
echo "Provide default when value is null or false"
echo "------------------------------------------------------------------"
echo ""
echo "Command: jq '.endpoints[] | {name, errors: (.errors // \"none\")}' /tmp/jq-04.json"
jq '.endpoints[] | {name, errors: (.errors // "none")}' /tmp/jq-04.json
echo ""
echo "Command: jq '.endpoints[] | {name, latency: (.latency // -1)}' /tmp/jq-04.json"
jq '.endpoints[] | {name, latency: (.latency // -1)}' /tmp/jq-04.json
echo ""
echo "Command: jq '.missing_key // \"default value\"' /tmp/jq-04.json"
jq '.missing_key // "default value"' /tmp/jq-04.json
echo ""

# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 4.4: NULL CHECKS"
echo "Explicit null handling"
echo "------------------------------------------------------------------"
echo ""
echo "Command: jq '.endpoints[] | select(.latency != null) | {name, latency}' /tmp/jq-04.json"
jq '.endpoints[] | select(.latency != null) | {name, latency}' /tmp/jq-04.json
echo ""
echo "Command: jq '.endpoints[] | select(.errors == null) | .name' /tmp/jq-04.json"
jq '.endpoints[] | select(.errors == null) | .name' /tmp/jq-04.json
echo ""
echo "Command: jq '[.endpoints[] | select(.latency)] | length' /tmp/jq-04.json"
echo "(Truthy check - null/false excluded)"
jq '[.endpoints[] | select(.latency)] | length' /tmp/jq-04.json
echo ""

# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 4.5: TRY-CATCH"
echo "Handle errors gracefully with try and ?"
echo "------------------------------------------------------------------"
echo ""
echo "Command: jq '.endpoints[] | try .missing.nested catch \"not found\"' /tmp/jq-04.json"
jq '.endpoints[] | try .missing.nested catch "not found"' /tmp/jq-04.json
echo ""
echo "Command: jq '.endpoints[] | .latency? // \"N/A\"' /tmp/jq-04.json"
echo "(? suppresses errors, // provides default)"
jq '.endpoints[] | .latency? // "N/A"' /tmp/jq-04.json
echo ""

# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 4.6: COMPARISON WITH THRESHOLDS"
echo "Real-world alerting logic"
echo "------------------------------------------------------------------"
echo ""
echo "Command: Get latency status based on thresholds"
echo 'jq '"'"'.thresholds as $t | .endpoints[] | select(.latency) | {
  name,
  latency,
  status: (
    if .latency >= $t.latency_crit then "CRITICAL"
    elif .latency >= $t.latency_warn then "WARNING"
    else "OK" end
  )
}'"'"' /tmp/jq-04.json'
jq '.thresholds as $t | .endpoints[] | select(.latency) | {name, latency, status: (if .latency >= $t.latency_crit then "CRITICAL" elif .latency >= $t.latency_warn then "WARNING" else "OK" end)}' /tmp/jq-04.json
echo ""

# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 4.7: AND/OR/NOT"
echo "Boolean operators"
echo "------------------------------------------------------------------"
echo ""
echo "Command: jq '.endpoints[] | select(.status == \"up\" and .latency < 100) | .name' /tmp/jq-04.json"
jq '.endpoints[] | select(.status == "up" and .latency < 100) | .name' /tmp/jq-04.json
echo ""
echo "Command: jq '.endpoints[] | select(.status == \"down\" or .status == \"degraded\") | .name' /tmp/jq-04.json"
jq '.endpoints[] | select(.status == "down" or .status == "degraded") | .name' /tmp/jq-04.json
echo ""
echo "Command: jq '.endpoints[] | select(.status != \"up\") | .name' /tmp/jq-04.json"
jq '.endpoints[] | select(.status != "up") | .name' /tmp/jq-04.json
echo ""

# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "YOUR TURN - TRY THESE:"
echo "------------------------------------------------------------------"
echo ""
echo "1. Find endpoints with errors (not null):"
echo "   jq '.endpoints[] | select(.errors != null) | {name, errors}' /tmp/jq-04.json"
echo ""
echo "2. Count healthy endpoints:"
echo "   jq '[.endpoints[] | select(.status == \"up\")] | length' /tmp/jq-04.json"
echo ""
echo "3. Get latency or 'unknown':"
echo "   jq -r '.endpoints[] | \"\\(.name): \\(.latency // \"unknown\")ms\"' /tmp/jq-04.json"
echo ""
echo "------------------------------------------------------------------"
echo "KEY TAKEAWAYS:"
echo "1. if cond then a else b end - conditional"
echo "2. // - alternative (default for null/false)"
echo "3. select(.field != null) - null check"
echo "4. try expr catch fallback - error handling"
echo "5. .field? - optional, suppress errors"
echo "6. and/or/not - boolean operators"
echo "------------------------------------------------------------------"