0Pricing
DevOps Bootcamp · บทเรียน

การแปลงและสร้างออบเจกต์ JSON ด้วย jq

ปรับรูปแบบข้อมูลด้วย map, to_entries และการสร้างออบเจกต์ เพื่อสร้างข้อมูล JSON ชุดใหม่

การแปลงและสร้างออบเจกต์ JSON ด้วย jq เป็นบทเรียน DevOps Bootcamp ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน DevOps Bootcamp และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส DevOps Bootcamp มีบทเรียนทั้งหมด 4 บทเรียน

เหตุใดจึงต้องแปลง JSON

JSON ดิบจาก API หรือไฟล์บันทึกมักไม่ได้มีรูปแบบตรงตามที่คุณต้องการ คุณอาจได้รับออบเจ็กต์ขนาดใหญ่แต่ต้องการเพียงบางฟิลด์ หรือต้องการเปลี่ยนชื่อคีย์ ทำโครงสร้างที่ซ้อนกันให้แบนราบ หรือสร้างข้อมูลใหม่ทั้งหมดเพื่อส่งไปยังบริการอื่น

jq เป็นตัวประมวลผล JSON บรรทัดคำสั่งที่มีขนาดเล็กแต่ทรงพลัง ทำให้การแปลงเหล่านี้ทำได้ในกระบวนการต่อเนื่องเดียว ในบทเรียนนี้คุณจะได้เรียนรู้เทคนิคหลักสามอย่างสำหรับปรับรูปข้อมูล:

  • การสร้างออบเจ็กต์ — สร้างออบเจ็กต์ JSON ใหม่ตั้งแต่ต้น
  • map — ใช้การแปลงกับทุกองค์ประกอบของอาร์เรย์
  • to_entries / from_entries — มองคู่คีย์-ค่าในออบเจ็กต์เป็นอาร์เรย์ เพื่อให้กรองและสร้างกลับขึ้นมาใหม่ได้

ตัวอย่างทั้งหมดสมมติว่าติดตั้ง jq แล้ว (apt install jq / brew install jq)

พื้นฐานการสร้างออบเจ็กต์

ความสามารถพื้นฐานที่สุดของ jq คือ การสร้างออบเจ็กต์: ครอบนิพจน์ด้วย {} เพื่อสร้างออบเจ็กต์ JSON ใหม่ คุณเลือกได้ว่าจะใส่ฟิลด์ใดบ้างและจะตั้งชื่อว่าอะไร

ไวยากรณ์:

  • { newKey: .existingField } — เปลี่ยนชื่อฟิลด์
  • { name, age } — รูปแบบย่อเมื่อคีย์ใหม่ตรงกับชื่อฟิลด์
  • { total: (.price * .qty) } — คำนวณค่าในบรรทัดเดียว

ส่วนย่อยของคำสั่งด้านล่างอ่าน JSON ของสินค้าและสร้างรูปแบบที่กระชับขึ้น โดยมีฟิลด์ 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)
}'

การสร้างออบเจ็กต์จากข้อมูลที่ซ้อนกัน

JSON ในการใช้งานจริงมักมีโครงสร้างซ้อนกัน jq ช่วยให้คุณเข้าถึงเส้นทางที่ซ้อนกันภายในตัวสร้างออบเจ็กต์ และทำให้โครงสร้างแบนราบได้ในเวลาเดียวกัน

ใช้สัญกรณ์เส้นทางแบบจุดภายในนิพจน์ค่าของตัวสร้าง:

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

ตัวอย่างด้านล่างนำระเบียนผู้ใช้ที่ซ้อนกันลึกมาสร้างเป็นสรุปแบบแบนราบ ซึ่งเหมาะสำหรับแถวส่วนหัวของ CSV หรือเนื้อหาคำขอ API

#!/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
}'

การแปลงอาร์เรย์ด้วย map

map(expr) เทียบเท่ากับการวนทำกับทุกองค์ประกอบใน jq: ใช้ expr กับทุกองค์ประกอบของอาร์เรย์อินพุต และส่งคืนอาร์เรย์ใหม่ที่มีความยาวเท่าเดิม

ประเด็นสำคัญ:

  • map(expr) เป็นรูปแบบย่อของ [.[] | expr]
  • นิพจน์ภายในอาจเป็นตัวกรอง jq ใด ๆ ก็ได้ รวมถึงการสร้างออบเจ็กต์
  • เชื่อมกับ select() เพื่อกรองก่อนแปลงข้อมูล

ส่วนย่อยของคำสั่งนี้ประมวลผลรายการคำสั่งซื้อ โดยเก็บไว้เฉพาะฟิลด์ที่จำเป็นสำหรับรายการจัดส่ง

#!/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 กับฟิลด์ที่คำนวณแล้ว

ภายใน map คุณสามารถคำนวณค่าใหม่ แปลงชนิดข้อมูล และรวมฟิลด์ต่าง ๆ ได้ ไม่ใช่เพียงคัดลอกข้อมูล รูปแบบที่ใช้บ่อย ได้แก่:

  • การแทรกข้อความ: "\(.first) \(.last)"
  • เลขคณิต: (.price * 1.2 | round) สำหรับการบวกราคาเพิ่ม 20%
  • เงื่อนไข: if .score >= 90 then "A" else "B" end

ตัวอย่างด้านล่างเพิ่มข้อมูลให้รายการพนักงาน โดยเพิ่ม fullName ที่คำนวณแล้วและป้ายกำกับ seniority ตามจำนวนปีของประสบการณ์

#!/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)
})'

ทำความเข้าใจ to_entries

to_entries แปลงออบเจ็กต์ JSON เป็นอาร์เรย์ของคู่ {key, value} ทำให้ใช้การดำเนินการกับอาร์เรย์ เช่น map, select และ sort กับฟิลด์ของออบเจ็กต์ได้ ซึ่งไม่สามารถทำกับออบเจ็กต์โดยตรง

ตัวอย่างการแปลง:

  • อินพุต: {"a": 1, "b": 2}
  • เอาต์พุต: [{"key": "a", "value": 1}, {"key": "b", "value": 2}]

การดำเนินการย้อนกลับคือ from_entries ซึ่งแปลงอาร์เรย์นั้นกลับเป็นออบเจ็กต์ ทั้งสองอย่างรวมกันเป็นรูปแบบ to_entries | map(...) | from_entries สำหรับแปลงข้อมูลระดับออบเจ็กต์

#!/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'

การกรองคีย์ด้วย to_entries

การใช้งาน to_entries ที่เป็นประโยชน์อย่างยิ่งคือ การกรองแบบไดนามิกว่าควรเก็บหรือลบคีย์ใด โดยพิจารณาจากชื่อคีย์เอง ซึ่งการสร้างออบเจ็กต์ทำไม่ได้เมื่อไม่ทราบชื่อคีย์ล่วงหน้า

รูปแบบ:

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

ส่วนย่อยของคำสั่งด้านล่างลบคีย์ทั้งหมดที่ขึ้นต้นด้วยขีดล่าง ซึ่งเป็นฟิลด์ภายในหรือฟิลด์ส่วนตัว ก่อนส่งต่อออบเจ็กต์การกำหนดค่าไปยังบริการภายนอก

#!/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
'

การเปลี่ยนชื่อคีย์แบบไดนามิกด้วย to_entries

การสร้างออบเจ็กต์ใช้เปลี่ยนชื่อคีย์เมื่อคุณทราบชื่อขณะเขียน แต่ to_entries ช่วยให้คุณเปลี่ยนชื่อคีย์ โดยใช้โปรแกรม ได้ เช่น แปลง camelCase เป็น snake_case หรือเพิ่มคำนำหน้า

ภายใน map คุณจะอัปเดตฟิลด์ .key ของแต่ละรายการ แล้วส่งต่อไปยัง from_entries:

  • map(.key |= gsub("(?<=[a-z])(?=[A-Z])"; "_") | .key |= ascii_downcase) — แปลง camelCase เป็น snake_case
  • map(.key |= "app_" + .) — เพิ่มคำนำหน้าให้ทุกคีย์

ตัวอย่างนี้เพิ่มคำนำหน้า APP_ ให้ชื่อตัวแปรสภาพแวดล้อมทั้งหมด เพื่อจัดกลุ่มชื่อก่อนแทรกเข้าไปในคอนเทนเนอร์

#!/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: รูปแบบย่อที่สะดวก

รูปแบบ to_entries | map(...) | from_entries ถูกใช้บ่อยมาก จน jq มีรูปแบบย่อให้ใช้ นั่นคือ with_entries(expr)

ให้ผลเทียบเท่ากันทุกประการ แต่กระชับกว่า:

  • with_entries(.value |= . * 2) — คูณค่าตัวเลขทุกค่าด้วยสอง
  • with_entries(select(.value != null)) — ลบคีย์ที่มีค่าเป็นค่าว่าง
  • with_entries(.key |= ascii_upcase) — เปลี่ยนคีย์ทั้งหมดเป็นตัวพิมพ์ใหญ่

ส่วนย่อยของคำสั่งนี้ลบคีย์ทั้งหมดที่มีค่าเป็น null หรือสตริงว่าง ซึ่งเป็นขั้นตอนทำความสะอาดที่ใช้บ่อยก่อนส่งคำขอ PATCH ไปยัง 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"

การรวม map และการสร้างออบเจ็กต์ในกระบวนการต่อเนื่อง

การแปลงข้อมูลจริงมักเชื่อมการดำเนินการ jq หลายอย่างเข้าด้วยกัน กระบวนการต่อเนื่องทั่วไปสำหรับเตรียมข้อมูลส่งไปยัง API อาจทำดังนี้:

  1. กรองอาร์เรย์อินพุตด้วย map(select(...))
  2. ปรับรูปแต่ละองค์ประกอบด้วยการสร้างออบเจ็กต์
  3. เพิ่มฟิลด์ที่คำนวณแล้ว
  4. เรียงลำดับผลลัพธ์

ตัวอย่างด้านล่างอ่านรายการตัวชี้วัดของเซิร์ฟเวอร์ เก็บเฉพาะเซิร์ฟเวอร์ที่มีการใช้งาน CPU สูง และสร้างข้อมูลแจ้งเตือนแบบกระชับพร้อมส่งด้วย POST ไปยังเว็บฮุก

#!/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"

การสร้างออบเจ็กต์ JSON ใหม่จากหลายแหล่ง

jq สามารถผสานอินพุตและสร้างออบเจ็กต์ที่ดึงข้อมูลจาก JSON หลายแหล่งได้ โดยใช้ ตัวดำเนินการบวก + และ การผูกตัวแปร ด้วย as $var

รูปแบบที่มีประโยชน์:

  • obj1 + obj2 — ผสานออบเจ็กต์สองตัว โดยค่าด้านขวาจะชนะเมื่อคีย์ขัดแย้งกัน
  • --argjson — ส่งเอกสาร JSON ตัวที่สองเป็นตัวแปร
  • $ENV — อ่านตัวแปรสภาพแวดล้อมโดยตรงภายใน jq

ส่วนย่อยของคำสั่งนี้ผสานการกำหนดค่าพื้นฐานกับการเขียนทับเฉพาะสภาพแวดล้อม ซึ่งเป็นรูปแบบที่ใช้บ่อยสำหรับจัดการการกำหนดค่าแอปพลิเคชันแบบ 12-factor ในสคริปต์เชลล์

#!/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"

ตรวจสอบความเข้าใจ: to_entries กับ map

คุณมีออบเจ็กต์ JSON ต่อไปนี้ และต้องการลบคีย์ทั้งหมดที่มี ค่าน้อยกว่า 0 เพื่อสร้างออบเจ็กต์ใหม่ที่มีเฉพาะค่าที่ไม่ติดลบ นิพจน์ jq ใดทำงานนี้ได้ถูกต้อง

อินพุต: {"a": 10, "b": -3, "c": 0, "d": 5}

สรุปบทเรียน: การแปลง JSON ด้วย jq

คุณได้เรียนรู้เทคนิคสำคัญสำหรับปรับรูป JSON ด้วย jq แล้ว:

  • การสร้างออบเจ็กต์ {} — สร้างออบเจ็กต์ใหม่โดยเลือก เปลี่ยนชื่อ และคำนวณฟิลด์จากอินพุต
  • map(expr) — ใช้การแปลงใด ๆ กับทุกองค์ประกอบของอาร์เรย์ รวมถึงการสร้างออบเจ็กต์ที่ซ้อนกันและการใช้ select() เพื่อกรอง
  • to_entries / from_entries — แปลงออบเจ็กต์เป็นอาร์เรย์ของคู่ {key, value} เพื่อให้ดำเนินการกับคีย์และค่าแบบอาร์เรย์ได้ แล้วแปลงกลับ
  • with_entries(expr) — รูปแบบย่อของกระบวนการต่อเนื่อง to_entries → map → from_entries ทั้งชุด
  • การผสานออบเจ็กต์ ด้วย + และ --argjson สำหรับข้อมูลจากหลายแหล่ง

องค์ประกอบเหล่านี้นำมาประกอบกันได้: กรองด้วย select ปรับรูปด้วยการสร้างออบเจ็กต์ เพิ่มข้อมูลด้วยฟิลด์ที่คำนวณแล้ว และเชื่อมทั้งหมดเข้าด้วยกันในนิพจน์ jq เดียวที่อ่านง่าย เมื่อเชี่ยวชาญรูปแบบเหล่านี้แล้ว คุณจะจัดการข้อมูล JSON แทบทุกชนิดได้โดยตรงในเชลล์ โดยไม่ต้องเขียนสคริปต์เฉพาะด้วย Python หรือ Node

คำถามที่พบบ่อย

บทเรียน “การแปลงและสร้างออบเจกต์ JSON ด้วย jq” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การแปลงและสร้างออบเจกต์ JSON ด้วย jq” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส DevOps Bootcamp ให้อัปเกรดเป็น CoddyKit PRO คอร์ส DevOps Bootcamp มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การแปลงและสร้างออบเจกต์ JSON ด้วย jq”

ปรับรูปแบบข้อมูลด้วย map, to_entries และการสร้างออบเจกต์ เพื่อสร้างข้อมูล JSON ชุดใหม่ คุณปฏิบัติ DevOps Bootcamp ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน DevOps Bootcamp หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน DevOps Bootcamp บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “การแปลงและสร้างออบเจกต์ JSON ด้วย jq” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน DevOps Bootcamp นี้ได้ไหม

ได้ บทเรียน DevOps Bootcamp ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การกรองและเลือก JSON ด้วยไปป์ไลน์ jq
  2. การแปลงและสร้างออบเจกต์ JSON ด้วย jq
  3. การใช้ REST API ด้วย curl และ jq ร่วมกัน
  4. การแก้ไขไฟล์การกำหนดค่า YAML ด้วย yq
← กลับไปที่ DevOps Bootcamp