0Pricing
Scala for Backend Engineering & Functional Programming · บทเรียน

ปลายทาง JSON

ผสาน http4s เข้ากับ Circe

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

JSON ผ่าน circe

http4s ผสานการทำงานกับ JSON ผ่านมอดูล http4s-circe ซึ่งเชื่อมตัวเข้ารหัสของ circe เข้ากับ EntityDecoder และ EntityEncoder โดย circe เป็นไลบรารี JSON เชิงฟังก์ชันสำหรับ Scala ที่ใช้งานกันเป็นมาตรฐานโดยพฤตินัย

คุณกำหนดอินสแตนซ์ Encoder และ Decoder สำหรับชนิดข้อมูลของคุณ แล้วให้ http4s จัดการรูปแบบข้อมูลบนเครือข่าย

// build.sbt
// "org.http4s" %% "http4s-circe" % http4sV
// "io.circe"   %% "circe-generic" % circeV

การสร้าง Codecs

เมื่อใช้ circe-generic คุณสามารถสร้าง codec โดยอัตโนมัติด้วย deriveEncoder/deriveDecoder หรือคำอธิบายประกอบ @JsonCodec ซึ่งจะจับคู่ฟิลด์ของคลาสแบบ case class กับคีย์ JSON ตามชื่อ

การสร้าง codec ต้องมี codec สำหรับชนิดของทุกฟิลด์ โดยทำซ้ำลงไปตามลำดับชั้น

import io.circe.generic.semiauto._

case class User(id: Int, name: String)
implicit val enc = deriveEncoder[User]
implicit val dec = deriveDecoder[User]

EntityEncoder จาก circe

การนำเข้า org.http4s.circe.CirceEntityEncoder._ จะให้ EntityEncoder[F, A] แบบ implicit สำหรับ A ใด ๆ ที่มี circe Encoder จากนั้น Ok(user) จะทำการทำให้เป็นอนุกรมเป็น JSON พร้อมชนิดเนื้อหา application/json

ในตัวจัดการคำขอไม่จำเป็นต้องแปลงเป็น Json ด้วยตนเอง

import org.http4s.circe.CirceEntityEncoder._

HttpRoutes.of[IO] {
  case GET -> Root / "me" => Ok(User(1, "Ada"))
}

EntityDecoder จาก circe

ในทางกลับกัน org.http4s.circe.CirceEntityDecoder._ จะจัดเตรียม EntityDecoder[F, A] สำหรับ A ใด ๆ ที่มี circe Decoder จากนั้น req.as[User] จะวิเคราะห์เนื้อความ JSON

การนำเข้าทั้งสองรายการรวมอยู่ใน CirceEntityCodec._

import org.http4s.circe.CirceEntityDecoder._

case req @ POST -> Root / "users" =>
  req.as[User].flatMap(u => Created(u))

POST ที่ใช้ JSON อย่างครบถ้วน

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

ความล้มเหลวในการถอดรหัสจะแสดงเป็น 422 หรือ 400 ผ่านตัวถอดรหัสของ circe

import org.http4s.circe.CirceEntityCodec._

case req @ POST -> Root / "users" =>
  for {
    in  <- req.as[User]
    out <- store.create(in)
    res <- Created(out)
  } yield res

ตัวแทรกสตริง json

สำหรับ JSON แบบเฉพาะกิจ ตัวแทรกสตริง json ของ circe จาก io.circe.literal จะสร้างค่า Json โดยตรงพร้อมค่าของ Scala ที่แทรกเข้ามา

เหมาะสำหรับการตอบกลับขนาดเล็กหรือข้อมูลทดสอบ โดยไม่ต้องสร้างคลาสแบบ case class

import io.circe.literal._

val body = json"""{ "status": "ok", "count": 3 }"""
Ok(body)

ชื่อฟิลด์แบบกำหนดเอง

เมื่อคีย์ JSON แตกต่างจากชื่อฟิลด์ของ Scala ให้สร้าง codec ด้วย Configuration จาก circe-generic-extras เช่น snake_case หรือเขียน codec เองโดยใช้ forProduct2

วิธีนี้แยกสัญญา API ออกจากการตั้งชื่อภายใน

import io.circe.Encoder

implicit val e: Encoder[User] =
  Encoder.forProduct2("user_id", "full_name")(u => (u.id, u.name))

การเข้ารหัสรายการ

circe มี codec สำหรับ List, Vector, Option และ Map ให้อัตโนมัติเมื่อมี codec ของสมาชิกแล้ว ดังนั้นการส่งคืนคอลเลกชันจึงทำงานได้ทันที

รายการว่างจะถูกเข้ารหัสเป็น [] ส่วน None จะกลายเป็นคีย์ที่ไม่มีอยู่หรือเป็น null

import org.http4s.circe.CirceEntityEncoder._

case GET -> Root / "users" =>
  store.all.flatMap(us => Ok(us)) // List[User] -> JSON array

การตรวจสอบ JSON ที่ถอดรหัสแล้ว

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

เก็บเงื่อนไขคงที่ของโดเมนไว้ในตัวสร้างอัจฉริยะที่คืนค่าเป็น Either เพื่อให้เข้าใจได้ชัดเจน

req.as[User].flatMap { u =>
  if (u.name.nonEmpty) Created(u)
  else BadRequest("name required")
}

การตอบกลับข้อผิดพลาดเป็น JSON

ส่งข้อผิดพลาดที่มีโครงสร้างเป็น JSON เพื่อให้ไคลเอนต์วิเคราะห์ได้ กำหนดคลาสแบบ case class สำหรับข้อผิดพลาดพร้อมตัวเข้ารหัสของ circe แล้วส่งให้ตัวสร้างสถานะที่เกี่ยวข้อง

รูปแบบข้อผิดพลาดที่สอดคล้องกันทำให้ใช้งาน API ได้ง่ายขึ้นมาก

case class ApiError(code: String, message: String)
implicit val e = deriveEncoder[ApiError]

BadRequest(ApiError("E_NAME", "name required"))

JSON แบบสตรีม

สำหรับคอลเลกชันขนาดใหญ่ คุณสามารถส่ง JSON แบบสตรีมแทนการเก็บทั้งหมดไว้ในหน่วยความจำ jsonEncoderOf ร่วมกับ fs2 Stream[F, A] จะส่งอาร์เรย์ JSON ออกมาอย่างต่อเนื่อง

วิธีนี้ทำให้การใช้หน่วยความจำคงที่แม้ชุดผลลัพธ์จะมีขนาดใหญ่ โดยอาศัยการควบคุมแรงดันย้อนกลับของ fs2

import org.http4s.circe.streamJsonArrayEncoder

case GET -> Root / "feed" =>
  Ok(store.streamAll) // fs2.Stream[IO, Event]

ตรวจสอบอย่างรวดเร็ว

ทบทวนว่าการนำเข้าใดทำให้สามารถถอดรหัสเนื้อความ JSON เป็นคลาสแบบ case class ได้

สรุป

คุณเชื่อมต่อ JSON ด้วย http4s-circe แล้ว โดยสร้าง codec นำเข้า CirceEntityCodec และใช้ Ok(value) / req.as[A] สำหรับการรับส่ง JSON อย่างครบถ้วน

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

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

บทเรียน “ปลายทาง JSON” ฟรีหรือไม่

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

คุณจะเรียนรู้อะไรในบทเรียน “ปลายทาง JSON”

ผสาน http4s เข้ากับ Circe คุณปฏิบัติ Scala for Backend Engineering & Functional Programming ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Scala for Backend Engineering & Functional Programming หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Scala for Backend Engineering & Functional Programming บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “ปลายทาง JSON” ใช้เวลานานแค่ไหน

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

ฉันเขียนและรันโค้ดในบทเรียน Scala for Backend Engineering & Functional Programming นี้ได้ไหม

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

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

  1. เส้นทางและ HttpRoutes
  2. คำขอและการตอบกลับ
  3. ปลายทาง JSON
  4. ให้บริการแอปพลิเคชัน
← กลับไปที่ Scala for Backend Engineering & Functional Programming