Intensiv DevOps-uddannelse · Lektion

Transformation og opbygning af JSON-objekter med jq

Omform data med map, to_entries og objektkonstruktion for at generere nye JSON-nyttelaster.

Lektion 2 af 413 trin

Transformation og opbygning af JSON-objekter med jq er en gratis Intensiv DevOps-uddannelse-lektion på CoddyKit. Dette er lektion 2 af 4. Du kan læse alle 3 lektioner i dette læringsspor gratis i deres fulde længde — derefter låser CoddyKit PRO alle lektioner op samt praktiske øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Den er en del af læringsforløbet i Intensiv DevOps-uddannelse, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Intensiv DevOps-uddannelse-kurset indeholder 4 lektioner i alt.

Hvorfor omforme JSON?

Rå JSON fra API'er eller logfiler har sjældent præcis den struktur, du har brug for. Du modtager måske et stort objekt, men ønsker kun bestemte felter, eller du har brug for at omdøbe nøgler, flade indlejrede strukturer ud eller opbygge en helt ny payload, som skal sendes til en anden tjeneste.

jq er en let og kraftfuld JSON-behandler til kommandolinjen, som gør disse omformninger mulige i en enkelt filterkæde. I denne lektion lærer du de tre grundlæggende teknikker til at ændre datastrukturen:

  • Konstruktion af objekter — opbyg et nyt JSON-objekt fra bunden
  • map — anvend en omformning på hvert element i et array
  • to_entries / from_entries — behandl et objekts nøgleværdi-par som et array, så du kan filtrere dem og opbygge dem igen

Alle eksempler forudsætter, at jq er installeret (apt install jq / brew install jq).

Grundlæggende konstruktion af objekter

Den mest grundlæggende funktion i jq er konstruktion af objekter: omslut udtryk med {} for at opbygge et nyt JSON-objekt. Du vælger, hvilke felter der skal med, og hvad de skal hedde.

Syntaks:

  • { newKey: .existingField } — omdøb et felt
  • { name, age } — kort form, når den nye nøgle har samme navn som feltet
  • { total: (.price * .qty) } — beregn en værdi direkte i udtrykket

Uddraget nedenfor læser en produkt-JSON og producerer en mere enkel struktur med det beregnede felt subtotal.

#!/usr/bin/env bash
# Object construction: pick and rename fields
product='{
  "id": 42,
  "name": "Widget Pro",
  "price": 9.99,
  "qty": 3,
  "warehouse": "EU-West"
}'

echo "$product" | jq '{
  productId: .id,
  name,
  subtotal: (.price * .qty)
}'

Opbygning af objekter fra indlejrede data

JSON fra den virkelige verden er ofte indlejret. jq lader dig tilgå indlejrede stier i en objektkonstruktion og flader samtidig strukturen ud.

Brug prikstienotation i konstruktørens værdiudtryk:

  • { city: .address.city }
  • { lat: .location.coords.lat }

Eksemplet nedenfor tager en dybt indlejret brugerpost og producerer en flad opsummering, der egner sig til en CSV-overskriftsrække eller brødteksten i en API-anmodning.

#!/usr/bin/env bash
user='{
  "id": "u-001",
  "profile": {
    "displayName": "Ada Lovelace",
    "contact": { "email": "ada@example.com", "phone": "+44-700" }
  },
  "plan": "pro"
}'

echo "$user" | jq '{
  id,
  name: .profile.displayName,
  email: .profile.contact.email,
  plan
}'

Omformning af arrays med map

map(expr) svarer i jq til en løkke, der kører for hvert element: Den anvender expr på hvert element i et input-array og returnerer et nyt array med samme længde.

Vigtige punkter:

  • map(expr) er en kortform for [.[] | expr]
  • Udtrykket indeni kan være et hvilket som helst jq-filter — herunder konstruktion af objekter
  • Kombinér med select() for at filtrere før omformningen

Uddraget behandler en liste over ordrer og beholder kun de felter, der er nødvendige for en forsendelsesoversigt.

#!/usr/bin/env bash
orders='[
  {"orderId": 1, "customer": "Alice", "total": 42.50, "status": "shipped"},
  {"orderId": 2, "customer": "Bob",   "total": 18.00, "status": "pending"},
  {"orderId": 3, "customer": "Carol", "total": 99.99, "status": "shipped"}
]'

# Produce a shipping manifest: only shipped orders, slim fields
echo "$orders" | jq '[
  .[] | select(.status == "shipped") | {
    id: .orderId,
    recipient: .customer,
    amount: .total
  }
]'

map med beregnede felter

I map kan du beregne nye værdier, konvertere typer og kombinere felter — ikke kun kopiere dem. Almindelige mønstre omfatter:

  • Tekstinterpolation: "\(.first) \(.last)"
  • Aritmetik: (.price * 1.2 | round) for et tillæg på 20 %
  • Betingelser: if .score >= 90 then "A" else "B" end

Eksemplet nedenfor udvider en liste over medarbejdere ved at tilføje et beregnet fullName og en seniority-etiket baseret på års erfaring.

#!/usr/bin/env bash
staff='[
  {"first": "Grace", "last": "Hopper",  "years": 15},
  {"first": "Alan",  "last": "Turing",  "years": 4},
  {"first": "Linus", "last": "Torvalds","years": 9}
]'

echo "$staff" | jq 'map({
  fullName: "\(.first) \(.last)",
  years,
  seniority: (if .years >= 10 then "senior" elif .years >= 5 then "mid" else "junior" end)
})'

Forståelse af to_entries

to_entries konverterer et JSON-objekt til et array af par på formen {key, value}. Det giver adgang til array-operationer (map, select, sort) på et objekts felter — noget, du ikke kan gøre direkte på et objekt.

Eksempel på omformning:

  • Input: {"a": 1, "b": 2}
  • Output: [{"key": "a", "value": 1}, {"key": "b", "value": 2}]

Den omvendte operation er from_entries, som omdanner arrayet tilbage til et objekt. Tilsammen udgør de idiomet to_entries | map(...) | from_entries til omformninger på objektniveau.

#!/usr/bin/env bash
# Demonstrate to_entries and from_entries
config='{"host": "db.local", "port": 5432, "ssl": true}'

echo "--- to_entries output ---"
echo "$config" | jq 'to_entries'

echo "--- round-trip back to object ---"
echo "$config" | jq 'to_entries | from_entries'

Filtrering af nøgler med to_entries

En af de mest praktiske anvendelser af to_entries er at filtrere dynamisk, hvilke nøgler der skal beholdes eller fjernes, baseret på selve nøglens navn — noget, som objektkonstruktion ikke kan gøre, når du ikke kender nøglenavnene på forhånd.

Mønster:

  • to_entries | map(select(.key | test("regex"))) | from_entries
  • to_entries | map(select(.key != "secret")) | from_entries

Uddraget nedenfor fjerner alle nøgler, der begynder med en understregning (interne/private felter), før et konfigurationsobjekt videresendes til en ekstern tjeneste.

#!/usr/bin/env bash
raw_config='{
  "endpoint": "https://api.example.com",
  "timeout": 30,
  "_internalToken": "s3cr3t",
  "_debugMode": true,
  "retries": 3
}'

# Remove any key starting with underscore
echo "$raw_config" | jq '
  to_entries
  | map(select(.key | startswith("_") | not))
  | from_entries
'

Dynamisk omdøbning af nøgler med to_entries

Objektkonstruktion omdøber nøgler, når du kender deres navne, mens du skriver koden. to_entries lader dig omdøbe nøgler programmatisk — for eksempel konvertere camelCase til snake_case eller tilføje et præfiks.

I map opdaterer du feltet .key for hvert element og sender derefter resultatet videre til from_entries:

  • map(.key |= gsub("(?<=[a-z])(?=[A-Z])"; "_") | .key |= ascii_downcase) — camelCase til snake_case
  • map(.key |= "app_" + .) — tilføj et præfiks til hver nøgle

Eksemplet giver alle miljøvariabelnavne præfikset APP_ for at placere dem i et navnerum, før de indsættes i en container.

#!/usr/bin/env bash
env_vars='{"host": "localhost", "port": "8080", "debug": "false"}'

# Add APP_ prefix and uppercase all keys
echo "$env_vars" | jq '
  to_entries
  | map({ key: ("APP_" + (.key | ascii_upcase)), value })
  | from_entries
'

with_entries: Den praktiske kortform

Mønsteret to_entries | map(...) | from_entries er så almindeligt, at jq har en kortform: with_entries(expr).

Det er præcis det samme, men mere kompakt:

  • with_entries(.value |= . * 2) — fordobl alle numeriske værdier
  • with_entries(select(.value != null)) — fjern nøgler med null-værdier
  • with_entries(.key |= ascii_upcase) — skriv alle nøgler med store bogstaver

Uddraget fjerner alle nøgler, hvis værdi er null eller en tom tekststreng — et almindeligt oprydningstrin, før en PATCH-anmodning sendes til en REST-API.

#!/usr/bin/env bash
patch_body='{
  "name": "Mehmet",
  "email": "",
  "phone": null,
  "city": "Istanbul"
}'

# Drop empty/null fields before PATCH
cleaned=$(echo "$patch_body" | jq '
  with_entries(select(.value != null and .value != ""))
')

echo "Cleaned payload:"
echo "$cleaned"

# In practice you would pipe to curl:
# curl -s -X PATCH https://api.example.com/users/1 \
#   -H "Content-Type: application/json" \
#   -d "$cleaned"

Kombination af map og objektkonstruktion i en filterkæde

Virkelige omformninger kæder flere jq-operationer sammen. En typisk filterkæde til klargøring af en API-payload kan:

  1. Filtrere input-arrayet med map(select(...))
  2. Ændre strukturen for hvert element med objektkonstruktion
  3. Tilføje beregnede felter
  4. Sortere resultatet

Eksemplet nedenfor læser en liste over servermålinger, beholder kun servere med højt CPU-forbrug og producerer en kompakt alarm-payload, der er klar til at blive sendt med POST til en webhook.

#!/usr/bin/env bash
metrics='[
  {"host": "web-01", "cpu": 23, "mem": 60, "region": "eu"},
  {"host": "web-02", "cpu": 91, "mem": 88, "region": "eu"},
  {"host": "db-01",  "cpu": 78, "mem": 95, "region": "us"},
  {"host": "db-02",  "cpu": 12, "mem": 40, "region": "us"}
]'

alerts=$(echo "$metrics" | jq '[
  .[] | select(.cpu > 75 or .mem > 85) | {
    server: .host,
    region,
    severity: (if .cpu > 90 or .mem > 90 then "critical" else "warning" end),
    metrics: { cpu: .cpu, mem: .mem }
  }
] | sort_by(.severity)')

echo "$alerts"

Opbygning af et nyt JSON-objekt fra flere kilder

jq kan flette input og konstruere objekter, der henter data fra flere JSON-kilder, ved hjælp af additionsoperatoren + og variabelbinding med as $var.

Nyttige mønstre:

  • obj1 + obj2 — flet to objekter (værdien på højre side vinder ved konflikter mellem nøgler)
  • --argjson — videregiv et andet JSON-dokument som en variabel
  • $ENV — læs miljøvariabler direkte i jq

Uddraget fletter en grundkonfiguration med miljøspecifikke tilsidesættelser — et almindeligt mønster til håndtering af konfiguration for 12-factor-applikationer i shell-scripts.

#!/usr/bin/env bash
base_config='{
  "logLevel": "info",
  "timeout": 30,
  "retries": 3,
  "database": "postgres://db.local/app"
}'

env_overrides='{
  "logLevel": "debug",
  "database": "postgres://db.staging/app_staging"
}'

# Merge: overrides win on conflicts
merged=$(echo "$base_config" | jq --argjson overrides "$env_overrides" '. + $overrides')

echo "Merged config:"
echo "$merged"

Videnstjek: to_entries kontra map

Du har følgende JSON-objekt og skal fjerne alle nøgler, hvis værdi er mindre end 0, så der dannes et nyt objekt med kun ikke-negative værdier. Hvilket jq-udtryk løser dette korrekt?

Input: {"a": 10, "b": -3, "c": 0, "d": 5}

Opsummering af lektionen: Omformning af JSON med jq

Du har gennemgået de vigtigste teknikker til at ændre strukturen i JSON med jq:

  • Objektkonstruktion {} — opbyg nye objekter ved at vælge, omdøbe og beregne felter fra et input
  • map(expr) — anvend en hvilken som helst omformning på hvert element i et array, herunder indlejret objektkonstruktion og select() til filtrering
  • to_entries / from_entries — konverter et objekt til et array af {key, value}-par, så du kan udføre array-operationer på nøgler og værdier, og konverter derefter tilbage
  • with_entries(expr) — den kompakte kortform for den fulde to_entries → map → from_entries-filterkæde
  • Fletning af objekter med + og --argjson til payloads fra flere kilder

Disse byggesten kan kombineres: filtrer med select, ændr strukturen med objektkonstruktion, udvid med beregnede felter, og kæd det hele sammen i ét læsbart jq-udtryk. Når du mestrer disse mønstre, kan du håndtere stort set enhver JSON-payload direkte i shellen uden at skrive et dedikeret script i Python eller Node.

Gratis at komme i gang

Lær Intensiv DevOps-uddannelse med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
142
Lektioner
568

Ofte stillede spørgsmål

Er lektionen “Transformation og opbygning af JSON-objekter med jq” gratis?

Ja — alle 3 lektioner i læringssporet Intensiv DevOps-uddannelse, inklusive “Transformation og opbygning af JSON-objekter med jq”, kan læses gratis i deres fulde længde her på webstedet. Derefter låser CoddyKit PRO alle lektioner op samt interaktive øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Intensiv DevOps-uddannelse-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Transformation og opbygning af JSON-objekter med jq”?

Omform data med map, to_entries og objektkonstruktion for at generere nye JSON-nyttelaster. Du øver dig i Intensiv DevOps-uddannelse med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på Intensiv DevOps-uddannelse?

Der kræves ingen tidligere erfaring. Intensiv DevOps-uddannelse på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 2 af 4.

Hvor lang tid tager lektionen “Transformation og opbygning af JSON-objekter med jq”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne Intensiv DevOps-uddannelse-lektion?

Ja. Alle Intensiv DevOps-uddannelse-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Filtrering og udvælgelse af JSON med jq-pipelines
  2. Transformation og opbygning af JSON-objekter med jq
  3. Brug af REST-API'er med curl og jq i kombination
  4. Redigering af YAML-konfigurationsfiler med yq
← Tilbage til Intensiv DevOps-uddannelse