Linux Command Line & Bash Scripting Mastery · บทเรียน

การใช้ REST API ด้วย curl และ jq ร่วมกัน

เชื่อมคำขอ curl เข้ากับ jq เพื่อดึงข้อมูล แบ่งหน้า และจัดรูปแบบการตอบกลับ API แบบสดในสคริปต์

บทเรียน 3 จาก 413 ขั้นตอน

การใช้ REST API ด้วย curl และ jq ร่วมกัน เป็นบทเรียน Linux Command Line & Bash Scripting Mastery ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Linux Command Line & Bash Scripting Mastery และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Linux Command Line & Bash Scripting Mastery มีบทเรียนทั้งหมด 4 บทเรียน

เหตุใด curl + jq จึงเป็นคู่หูทรงพลัง

REST API ส่งคืน JSON ส่วน curl ใช้ดึงการตอบกลับดิบ และ jq ใช้ตัด แบ่งกรอง และปรับรูปข้อมูล ทั้งหมดนี้ทำได้ในกระบวนการต่อเนื่องเดียว ไม่ต้องใช้สคริปต์ Python, Postman หรือไฟล์ชั่วคราว

  • curl จัดการ HTTP ได้แก่ เมธอด ส่วนหัว การยืนยันตัวตน และการเปลี่ยนเส้นทาง
  • jq จัดการ JSON ได้แก่ การกรอง การแมป การแปลง และการจัดรูปแบบ
  • การส่งข้อมูลต่อระหว่างทั้งสองทำให้เกิดเวิร์กโฟลว์ API ที่กระชับและนำมาประกอบกันได้

บทเรียนนี้จะพัฒนาทักษะดังกล่าวตั้งแต่หลักการพื้นฐาน ไปจนถึงรูปแบบการแบ่งหน้าและการเขียนสคริปต์ที่ใช้จริง

กระบวนการต่อเนื่องพื้นฐานจาก curl ไปยัง jq

รูปแบบที่ง่ายที่สุดคือส่งเอาต์พุตของ curl ต่อเข้า jq โดยตรง ใช้ -s (ทำงานแบบเงียบ) เพื่อซ่อนมาตรวัดความคืบหน้าของ curl ทำให้มีเพียงเนื้อหา JSON เท่านั้นที่ส่งต่อไปยัง jq

  • -s — โหมดเงียบ ไม่มีแถบความคืบหน้า
  • . — ตัวกรองเอกลักษณ์ของ jq ใช้พิมพ์การตอบกลับทั้งหมดในรูปแบบอ่านง่าย
  • -r ของ jq — เอาต์พุตดิบ ไม่มีเครื่องหมายคำพูดครอบสตริง
#!/usr/bin/env bash
# Fetch a public endpoint and pretty-print the JSON
curl -s 'https://jsonplaceholder.typicode.com/todos/1' | jq '.'

# Extract just the title field as a plain string
curl -s 'https://jsonplaceholder.typicode.com/todos/1' | jq -r '.title'

การตั้งค่าส่วนหัวคำขอและส่งโทเค็นยืนยันตัวตน

API สำหรับใช้งานจริงส่วนใหญ่ต้องการส่วนหัว Authorization หรือคีย์ API ให้ส่งส่วนหัวด้วย -H และเก็บข้อมูลลับไว้ในตัวแปรสภาพแวดล้อม อย่าเขียนข้อมูลเหล่านี้ไว้ตายตัวในโค้ด

  • -H 'Authorization: Bearer $TOKEN' — แทรกส่วนหัวสำหรับยืนยันตัวตน
  • -H 'Accept: application/json' — ระบุชัดเจนว่าต้องการให้ส่ง JSON กลับมา
  • ตัวแปรจะถูกขยายค่าภายในเครื่องหมายคำพูดคู่ ให้ใช้ " ครอบสตริงส่วนหัว
#!/usr/bin/env bash
TOKEN="${GITHUB_TOKEN}"   # set in your shell environment
USER="octocat"

curl -s \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Accept: application/vnd.github+json" \
  "https://api.github.com/users/${USER}" \
| jq '{login: .login, repos: .public_repos, followers: .followers}'

การกรองอาร์เรย์ — .[] และ select()

API มักส่งคืนอาร์เรย์ ใช้ .[] เพื่อวนผ่านทุกองค์ประกอบ จากนั้นใช้ select() เพื่อเก็บเฉพาะรายการที่ตรงตามเงื่อนไข

  • .[] — แยกอาร์เรย์ออกเป็นลำดับของออบเจ็กต์
  • select(.field == value) — เก็บเฉพาะออบเจ็กต์ที่ตรงกัน
  • เชื่อมตัวกรองหลายตัวด้วย |
#!/usr/bin/env bash
# Fetch all todos and keep only the completed ones
curl -s 'https://jsonplaceholder.typicode.com/todos' \
| jq '[.[] | select(.completed == true) | {id, title}]'

# Count how many are completed
curl -s 'https://jsonplaceholder.typicode.com/todos' \
| jq '[.[] | select(.completed == true)] | length'

การดึงหลายฟิลด์ด้วย map()

map() ใช้การแปลงกับสมาชิกทุกตัวของอาร์เรย์และส่งคืนอาร์เรย์ใหม่ ซึ่งเทียบเท่ากับ [.[] | ...] แต่มีความอ่านง่ายกว่า

  • map({key: .field}) — ปรับโครงสร้างออบเจ็กต์ทุกตัว
  • ใช้ร่วมกับ @csv หรือ @tsv เพื่อสร้างผลลัพธ์แบบตาราง
  • ใช้ -r ร่วมกับ @csv/@tsv เพื่อให้ได้ข้อความดิบ (ไม่มีการใส่เครื่องหมายอัญประกาศแบบ JSON)
#!/usr/bin/env bash
# Reshape a posts list into id + title pairs
curl -s 'https://jsonplaceholder.typicode.com/posts' \
| jq 'map({id, title: .title[0:40]})'

# Output as CSV for import into a spreadsheet
curl -s 'https://jsonplaceholder.typicode.com/posts' \
| jq -r '.[] | [.id, .userId, .title] | @csv'

รูปแบบการแบ่งหน้า — วนซ้ำจนกว่าจะได้หน้าว่าง

API ส่วนใหญ่จะแบ่งผลลัพธ์ออกเป็นหน้า รูปแบบที่ใช้กันทั่วไปคือการวนซ้ำด้วย while ซึ่งเพิ่มตัวนับหน้าไปเรื่อย ๆ และหยุดเมื่ออาร์เรย์ที่ส่งกลับมาว่างเปล่า

  • เก็บการตอบกลับจาก curl ไว้ในตัวแปรด้วย $(curl ...)
  • ใช้ jq 'length' เพื่อตรวจสอบว่าหน้านั้นมีรายการหรือไม่
  • สะสมผลลัพธ์ด้วย jq -s (รวมข้อมูลทั้งหมด) หรือเพิ่มต่อท้ายไฟล์
#!/usr/bin/env bash
# Paginate through jsonplaceholder posts (simulated: page stops at page 2
# because the API returns the full list regardless of ?_page, but the
# pattern is correct for real paginated APIs)

PAGE=1
PER_PAGE=10
OUTPUT="all_posts.json"
echo '[]' > "$OUTPUT"

while true; do
  RESPONSE=$(curl -s "https://jsonplaceholder.typicode.com/posts?_page=${PAGE}&_limit=${PER_PAGE}")
  COUNT=$(echo "$RESPONSE" | jq 'length')

  if [ "$COUNT" -eq 0 ]; then
    echo "No more pages. Stopping at page $((PAGE - 1))."
    break
  fi

  # Merge new items into the accumulated JSON array
  CURRENT=$(cat "$OUTPUT")
  echo "$CURRENT" "$RESPONSE" | jq -s '.[0] + .[1]' > "$OUTPUT"
  echo "Page $PAGE: fetched $COUNT items."
  PAGE=$((PAGE + 1))
done

echo "Total collected: $(jq 'length' "$OUTPUT")"

การแบ่งหน้าด้วยส่วนหัว Link (รูปแบบของ GitHub)

GitHub และ API อื่น ๆ อีกมากมายใช้ส่วนหัวการตอบกลับ Link เพื่อระบุ URL ของหน้าถัดไป คุณต้องแยกวิเคราะห์ส่วนหัวนี้ แทนการคาดเดา URL

  • curl -i จะรวมส่วนหัวการตอบกลับไว้ในเอาต์พุตมาตรฐาน หรือใช้ -D - เพื่อส่งส่วนหัวออกไปยังเอาต์พุตมาตรฐาน
  • แยกวิเคราะห์ส่วนหัว Link: <url>; rel="next" ด้วย grep และ sed
  • วนซ้ำจนกว่าจะไม่มีลิงก์ rel="next" อยู่
#!/usr/bin/env bash
# Follow Link-header pagination (GitHub repos example)
# Requires GITHUB_TOKEN in environment
TOKEN="${GITHUB_TOKEN}"
NEXT_URL="https://api.github.com/users/torvalds/repos?per_page=5"
ALL_REPOS="[]"

while [ -n "$NEXT_URL" ]; do
  # Capture full response (headers + body) to a temp file
  TMPFILE=$(mktemp)
  curl -sD "$TMPFILE" \
    -H "Authorization: Bearer ${TOKEN}" \
    -H "Accept: application/vnd.github+json" \
    "$NEXT_URL" \
  | {
      BODY=$(cat)
      ALL_REPOS=$(echo "$ALL_REPOS" "$BODY" | jq -s '.[0] + .[1]')
      echo "$ALL_REPOS" > /tmp/repos_acc.json
    }

  # Extract next URL from Link header
  NEXT_URL=$(grep -i '^link:' "$TMPFILE" \
    | sed -E 's/.*<([^>]+)>; rel="next".*/\1/;t;d')
  rm -f "$TMPFILE"
done

echo "Total repos: $(jq 'length' /tmp/repos_acc.json)"

การเชื่อมคำขอ — ใช้ผลลัพธ์จากการเรียกหนึ่งเป็นอินพุตของอีกการเรียก

ลำดับการทำงานที่ใช้กันทั่วไปคือ ดึงรายการออกมา ดึง ID ออกมา แล้วดึงรายละเอียดของแต่ละ ID เก็บค่าระหว่างทางด้วยการแทนที่คำสั่ง $() แล้วส่งค่าเหล่านั้นไปยัง URL ถัดไป

  • ดึงค่าเดียวด้วย jq -r '.field'
  • วนซ้ำกับ ID หลายค่าโดยใช้ jq -r '.[].id' ภายในลูป while read
  • ใช้ sleep ระหว่างคำขอเพื่อปฏิบัติตามข้อจำกัดอัตราการเรียก
#!/usr/bin/env bash
# Step 1: get all user IDs from the /users endpoint
# Step 2: for each user, fetch their posts and count them

curl -s 'https://jsonplaceholder.typicode.com/users' \
| jq -r '.[].id' \
| while read -r USER_ID; do
    POST_COUNT=$(curl -s "https://jsonplaceholder.typicode.com/posts?userId=${USER_ID}" \
                 | jq 'length')
    echo "User ${USER_ID}: ${POST_COUNT} posts"
    sleep 0.1   # be polite to the API
done

คำขอ POST — การส่งข้อมูล JSON

หากต้องการสร้างหรืออัปเดตทรัพยากร ให้ส่ง POST หรือ PUT พร้อมเนื้อหา JSON ใช้ -X POST, -H 'Content-Type: application/json' และ -d สำหรับเนื้อหา สร้างข้อมูลที่จะส่งด้วย jq -n เพื่อหลีกเลี่ยงปัญหาการใส่เครื่องหมายอัญประกาศ

  • jq -n --arg key value '{key: $key}' — แทรกค่าตัวแปรใน jq อย่างปลอดภัย
  • ส่ง JSON ที่สร้างขึ้นโดยตรงไปยัง -d @- ของ curl (อ่านเนื้อหาจากอินพุตมาตรฐาน)
  • แยกวิเคราะห์การตอบกลับทันทีด้วยตัวกรอง jq อีกตัว
#!/usr/bin/env bash
TITLE="My New Post"
BODY_TEXT="Written via curl and jq."
USER_ID=1

# Build the JSON payload safely and POST it
RESPONSE=$(jq -n \
  --arg title   "$TITLE" \
  --arg body    "$BODY_TEXT" \
  --argjson userId "$USER_ID" \
  '{title: $title, body: $body, userId: $userId}' \
| curl -s \
    -X POST \
    -H 'Content-Type: application/json' \
    -d @- \
    'https://jsonplaceholder.typicode.com/posts')

echo "Created post ID: $(echo "$RESPONSE" | jq '.id')"
echo "Full response:"
echo "$RESPONSE" | jq '.'

การจัดการข้อผิดพลาด — รหัสสถานะ HTTP และข้อผิดพลาดของ API

การเชื่อมต่อ HTTP สำเร็จไม่ได้หมายความว่าการเรียก API สำเร็จด้วย ให้ตรวจสอบรหัสสถานะ HTTP และฟิลด์ข้อผิดพลาดใน JSON แยกกัน

  • curl -w '%{http_code}' จะต่อรหัสสถานะท้ายเอาต์พุตมาตรฐาน ใช้ -o เพื่อเขียนเนื้อหาลงไฟล์
  • เปรียบเทียบรหัสในสคริปต์ แล้วจัดการกรณี 4xx/5xx ให้แตกต่างกัน
  • API จำนวนมากฝัง {"error": "..."} ไว้ในเนื้อหา ให้ตรวจสอบด้วย has() หรือ type ของ jq
#!/usr/bin/env bash
API_URL='https://jsonplaceholder.typicode.com/todos/99999'
TMPBODY=$(mktemp)

HTTP_CODE=$(curl -s -o "$TMPBODY" -w '%{http_code}' "$API_URL")

if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
  echo "Success ($HTTP_CODE):"
  jq '.' "$TMPBODY"
elif [ "$HTTP_CODE" -eq 404 ]; then
  echo "Resource not found (404). Body:"
  jq '.' "$TMPBODY"
elif [ "$HTTP_CODE" -ge 500 ]; then
  echo "Server error ($HTTP_CODE). Retrying later."
else
  echo "Unexpected status: $HTTP_CODE"
  cat "$TMPBODY"
fi

rm -f "$TMPBODY"

การสร้างฟังก์ชันตัวช่วย API ที่นำกลับมาใช้ซ้ำได้

รวมโค้ดมาตรฐานสำหรับ curl และการตรวจสอบข้อผิดพลาดไว้ในฟังก์ชันของเชลล์ ฟังก์ชันนี้จัดการการยืนยันตัวตน การตรวจสอบสถานะ และการดึงข้อมูล JSON ส่วนผู้เรียกเพียงส่งปลายทางกับตัวกรอง jq

  • ส่งคืนรหัสออกจากโปรแกรมที่ไม่ใช่ศูนย์เมื่อเกิดข้อผิดพลาด HTTP เพื่อให้ผู้เรียกใช้ || หรือ set -e ได้
  • รับอาร์กิวเมนต์ตัวกรอง jq เพื่อให้ฟังก์ชันเดียวกันรองรับปลายทางได้หลายแบบ
  • โหลดไฟล์ฟังก์ชันนี้จากสคริปต์ใด ๆ ที่ต้องใช้ API
#!/usr/bin/env bash
# api_get <endpoint_path> <jq_filter>
# Returns filtered JSON or exits non-zero on error.
api_get() {
  local PATH_PART="$1"
  local JQ_FILTER="${2:-.}"
  local BASE_URL='https://jsonplaceholder.typicode.com'
  local TMPBODY
  TMPBODY=$(mktemp)

  local HTTP_CODE
  HTTP_CODE=$(curl -s \
    -o "$TMPBODY" \
    -w '%{http_code}' \
    "${BASE_URL}${PATH_PART}")

  if [ "$HTTP_CODE" -lt 200 ] || [ "$HTTP_CODE" -ge 300 ]; then
    echo "[ERROR] HTTP $HTTP_CODE for ${PATH_PART}" >&2
    rm -f "$TMPBODY"
    return 1
  fi

  jq -r "$JQ_FILTER" "$TMPBODY"
  rm -f "$TMPBODY"
}

# Usage examples
api_get '/todos/1' '.title'
api_get '/posts?userId=1' '[.[] | .title]'
api_get '/users' '.[] | "\(.id) \(.name) <\(.email)>"'

ตรวจสอบความรู้: กลยุทธ์การแบ่งหน้า

ทดสอบความเข้าใจของคุณเกี่ยวกับการจัดการการตอบกลับจาก REST API ที่แบ่งหน้าในสคริปต์ Bash โดยใช้ curl และ jq

สรุปบทเรียน: การเขียนสคริปต์ API ด้วย curl + jq

ขณะนี้คุณมีชุดเครื่องมือครบถ้วนสำหรับเรียกใช้ REST API จากบรรทัดคำสั่ง Bash แล้ว:

  • ไปป์ไลน์พื้นฐาน: curl -s URL | jq 'filter' — พื้นฐานของทุกอย่าง
  • ส่วนหัวการยืนยันตัวตน: ส่งโทเค็นผ่าน -H จากตัวแปรสภาพแวดล้อม อย่าเขียนค่าไว้ตายตัวในสคริปต์
  • การจัดการอาร์เรย์: .[], select() และ map() ใช้เลือกบางส่วนและปรับโครงสร้างการตอบกลับจาก API
  • การแบ่งหน้า: วนซ้ำด้วยตัวนับหน้า (ใช้ อาร์เรย์ว่างเป็นตัวบ่งชี้) หรือแยกวิเคราะห์ส่วนหัว Link สำหรับ API รูปแบบที่ระบุ URL หน้าถัดไป
  • การเชื่อมคำขอ: ดึง ID จากการตอบกลับหนึ่งครั้ง แล้วส่งต่อไปยังคำขอถัดไปภายในลูป while read
  • POST พร้อมข้อมูลที่ปลอดภัย: สร้างเนื้อหา JSON ด้วย jq -n --arg แล้วส่งต่อไปยัง -d @- ของ curl
  • การจัดการข้อผิดพลาด: แยกสถานะ HTTP (-w '%{http_code}') ออกจากข้อผิดพลาดระดับ API ในเนื้อหา
  • ตัวช่วยที่นำกลับมาใช้ซ้ำได้: รวมโค้ดมาตรฐานไว้ในฟังก์ชันของเชลล์ เพื่อให้สคริปต์กระชับและเป็นไปตาม DRY

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

เริ่มต้นได้ฟรี

เรียนรู้ Bash ด้วย AI tutor — ฟรี

เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป

คอร์ส
22
บทเรียน
88

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

บทเรียน “การใช้ REST API ด้วย curl และ jq ร่วมกัน” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การใช้ REST API ด้วย curl และ jq ร่วมกัน” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Linux Command Line & Bash Scripting Mastery ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Linux Command Line & Bash Scripting Mastery มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การใช้ REST API ด้วย curl และ jq ร่วมกัน”

เชื่อมคำขอ curl เข้ากับ jq เพื่อดึงข้อมูล แบ่งหน้า และจัดรูปแบบการตอบกลับ API แบบสดในสคริปต์ คุณปฏิบัติ Linux Command Line & Bash Scripting Mastery ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Linux Command Line & Bash Scripting Mastery หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Linux Command Line & Bash Scripting Mastery บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “การใช้ REST API ด้วย curl และ jq ร่วมกัน” ใช้เวลานานแค่ไหน

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

ฉันเขียนและรันโค้ดในบทเรียน Linux Command Line & Bash Scripting Mastery นี้ได้ไหม

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

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

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