Go มันก็แปลง JSON ง่ายนิดเดียว! (ถ้าไม่เผลอพลาด)

สวัสดีครับ! วันนี้ผมอยากเล่าเรื่องการทำงานกับ JSON ใน Go (Golang) ให้ฟัง. แรกๆ ที่ผมเริ่มเขียน Go เนี่ย ยอมรับเลยว่าแอบ งง นิดๆ กับเรื่อง struct กับ tag ว่ามันจะแปลงเป็น JSON ได้ไงฟะ? แต่พอเข้าใจคอนเซ็ปต์แล้วมันก็โคตร ง่ายเลยนะ

พื้นฐานก่อน Go เนี่ย มันมี encoding/json มาให้ในตัวเลย ไม่ต้อง ลง package เพิ่มให้วุ่นวาย. เวลาเราจะแปลง struct เป็น JSON (Marshal) หรือแปลง JSON กลับมาเป็น struct (Unmarshal) เนี่ย มันใช้สองฟังก์ชันนี้แหละ

สมมติเรามี struct ง่ายๆ แบบนี้:

package main

import "fmt"
import "encoding/json"

type User struct {
    ID        int    `json:"id"`
    Name      string `json:"name"`
    Email     string `json:"email,omitempty"` // omitempty คือถ้าค่าว่าง (zero value) จะไม่เอาเข้า JSON
    IsActive  bool   `json:"is_active"`
    CreatedAt string `json:"created_at"`
}

func main() {
    // สร้าง User object
    u := User{
        ID:        1,
        Name:      "บักหำน้อย",
        Email:     "[email protected]",
        IsActive:  true,
        CreatedAt: "2023-10-27T10:00:00Z",
    }

    // Marshal (แปลง struct เป็น JSON)
    jsonData, err := json.Marshal(u)
    if err != nil {
        fmt.Println("Error marshalling JSON:", err)
        return
    }
    fmt.Println("JSON จาก Struct:")
    fmt.Println(string(jsonData))

    fmt.Println("\n---")

    // Unmarshal (แปลง JSON กลับมาเป็น struct)
    jsonString := `{"id":2,"name":"เจ๊แต๋ว","email":"[email protected]","is_active":false,"created_at":"2023-10-27T11:00:00Z"}`
    var newUser User
    err = json.Unmarshal([]byte(jsonString), &newUser)
    if err != nil {
        fmt.Println("Error unmarshalling JSON:", err)
        return
    }
    fmt.Println("Struct จาก JSON:")
    fmt.Printf("ID: %d, Name: %s, Email: %s, IsActive: %t\n", newUser.ID, newUser.Name, newUser.Email, newUser.IsActive)

}

รันโค้ดบนจะเห็นผลลัพธ์ประมาณนี้:

JSON จาก Struct:
{"id":1,"name":"บักหำน้อย","email":"[email protected]","is_active":true,"created_at":"2023-10-27T10:00:00Z"}

---
Struct จาก JSON:
ID: 2, Name: เจ๊แต๋ว, Email: [email protected], IsActive: false

สิ่งที่ผมเคยเจอตอนทำโปรเจกต์ (Error เล็กๆ แต่โคตรน่าหงุดหงิด) อันนี้จริงๆ มันไม่ใช่ Error แบบโปรแกรมพัง แต่มันคือ "Data ไม่มาตามที่คิด" นั่นแหละ สมมติคุณได้รับ JSON มาแบบนี้ (จาก API ปลายทางอะไรก็ได้):

{
  "userId": 123,
  "userName": "Boss",
  "isActive": "true"  <-- ตรงนี้แหละตัวดี
}

แล้วเราดันไปประกาศ struct แบบนี้:

type APIResponse struct {
    UserID   int    `json:"userId"`
    UserName string `json:"userName"`
    IsActive bool   `json:"isActive"` // หวังว่าจะได้ bool ใช่ไหม?
}

พอคุณเอาไป json.Unmarshal ปุ๊บ โอกาสที่คุณจะเจอ false ใน IsActive ทั้งที่ใน JSON มันเป็น "true" สูงมาก หรือบางทีก็ Error ไปเลย เพราะ Go มันคาดหวัง bool (true/false) จริงๆ ไม่ใช่ string "true"/"false"

ตัวอย่าง Error ที่เจอ: ถ้าเราลองทำแบบนี้

package main

import (
    "encoding/json"
    "fmt"
)

type BadUser struct {
    ID        int    `json:"id"`
    IsActive  bool   `json:"is_active"`
}

func main() {
    badJsonString := `{"id":1,"is_active":"true"}` // is_active เป็น string แทนที่จะเป็น bool
    var badUser BadUser
    err := json.Unmarshal([]byte(badJsonString), &badUser)
    if err != nil {
        fmt.Println("เฮ้ย! เกิด Error ตอน Unmarshal:", err)
        // Error ที่เจอจริงจะประมาณนี้:
        // เฮ้ย! เกิด Error ตอน Unmarshal: json: cannot unmarshal string into Go struct field BadUser.is_active of type bool
        return
    }
    fmt.Printf("BadUser: %+v\n", badUser)
}

เห็นไหม! มันจะฟ้องเลยว่า "cannot unmarshal string into Go struct field ... of type bool" วิธีแก้ก็คือ ต้องไปดู type ใน JSON ที่ได้รับมาดีๆ ว่ามันเป็น string หรือ bool หรือ int กันแน่. ถ้ามันไม่ตรง ก็ต้องปรับ struct เราให้ตรง หรือ ไม่ก็ต้องเขียน Custom Unmarshaler ซึ่งอันนั้นมันจะแอดวานซ์ไปหน่อย. สำหรับมือใหม่แค่รู้ว่ามันเกิดแบบนี้ได้ก็พอละ

สรุปแล้ว การจัดการ JSON ใน Go ไม่ได้ยากอย่างที่คิด แค่ต้องระวังเรื่อง type mismatch ให้ดีๆ ครับ. ถ้าติดตรงไหนลองพิมพ์ดู error ที่เจอแล้ว Search Google ดู ส่วนใหญ่จะมีคนเจอเหมือนๆ กันเยอะแยะ! โชคดีครับ!

Read more

PPV คืออะไร? เจาะลึกปรากฏการณ์ Pay-Per-View กับอีเวนต์สุดพิเศษแห่งยุค

PPV คืออะไร? เจาะลึกปรากฏการณ์ Pay-Per-View กับอีเวนต์สุดพิเศษแห่งยุค

ทำความเข้าใจ Pay-Per-View (PPV) กับเทรนด์การรับชมอีเวนต์สุดพิเศษ ทั้งศึก ONE Championship, คอนเสิร์ต Project Sekai และความบันเทิงหลากหลายผ่าน ABEMA PPV.

By ทีมงาน devdog
Xiaomi 17T เผยโฉมภาพจริงจาก Anatel ลุ้นเปิดตัว พ.ค. นี้ พร้อมดีไซน์ใหม่และชาร์จไว 67W!

Xiaomi 17T เผยโฉมภาพจริงจาก Anatel ลุ้นเปิดตัว พ.ค. นี้ พร้อมดีไซน์ใหม่และชาร์จไว 67W!

พบภาพจริง Xiaomi 17T จาก Anatel เผยดีไซน์ใหม่ กล้อง Leica ชิป Dimensity 8500 แบต 6500mAh และชาร์จไว 67W ลุ้นเปิดตัวเดือนพฤษภาคมนี้!

By ทีมงาน devdog
เอลนีโญกลับมาแล้ว! WMO เตือนรุนแรงทั่วโลก ไทยต้องเตรียมรับมือวิกฤตความร้อน

เอลนีโญกลับมาแล้ว! WMO เตือนรุนแรงทั่วโลก ไทยต้องเตรียมรับมือวิกฤตความร้อน

องค์การอุตุนิยมวิทยาโลกเตือนปรากฏการณ์เอลนีโญรุนแรงในปี 2026 อาจทำโลกเผชิญปีที่ร้อนที่สุด. เรียนรู้ผลกระทบและการเตรียมพร้อมของไทย.

By ทีมงาน devdog