[Golang] How to parse JSON

Visarut Junsone
Lazy-Dev
Published in
2 min readDec 27, 2018

ในครั้งนี้เราจะพูดเรื่องที่ทั่วไปที่สุด และ เป็นสิ่งที่ยังไงก็ต้องใช้ในการรับ input เข้า APIs นั้นก็คือ JSON และแน่นอน เมื่อเรารับค่า JSON เข้าไป ในแต่ละ Computer programming language นั้น มีการรับมือกับค่านี้ต่างกัน เช่น PHP ทำการแปลง JSON ให้เป็น Object ด้วย json_decode($string, true) เพื่อใช้งาน

เราจะพูดถึงการแปลง JSON เพื่อมาใช้งาน ใน GO-lang ซึ่งใช้หลักการเดียวกันคือการแปลงเป็นสิ่งที่เราต้องการ ใน GO-lang เราสามารถจะพบเจอการแปลงอยู่ 2 แบบ

  1. Structured data
  2. Unstructured data

Structured data

วิธีนี้ก็สมชื่อครับ เป็น ข้อมูลที่มีโครงสร้างชัดเจน นั้นหมายความว่า ทั้งตัวส่งและตัวรับนั้น จะต้องมีลักษณะเดียวกัน เช่น

// This is JSON input example
{
"name": "Atom",
"age": 5
}
// Person is an object to collect person data
type Person struct {
Name string
Age int
}

จาก Code snippet ด้านบน จะเห็นว่า JSON input จะมี name และ age ที่ตรงกันทั้งชื่อและประเภทของ value

package mainimport (
"fmt"
"encoding/json"
)
// Person is an object to collect person data
type Person struct {
Name string
Age int
}
func main() {
// This is JSON input example
myJsonString := `
{
"name": "Atom",
"age": 5
}
`
fmt.Println(myJsonString)
var p1 Person
json.Unmarshal([]byte(myJsonString), &p1)
fmt.Printf("Name: %s, Age: %d", p1.Name, p1.Age)
}

จากตัวอย่างโค้ด เริ่มต้นที่ฟังก์ชั่น main() ประกาศ และ ให้ค่า JSON string ไว้ ชื่อ myJsonString และ ประกาศ p1 ให้เป็น Person

จากนั้น ใช้ คำสั่ง json.Unmarshal ซึ่งต้องมีการ import “encoding/json” และ พารามิเตอร์ตัวแรกต้องเป็น []byte จึงทำการแปลง string เป็น []byte ด้วย type cast พารามิเตอร์ตัวที่สองนั้นจะเป็น object อะไรก็ได้ แต่ต้องส่งเป็น address เข้าไป เนื่องจาก ผลลัพธ์ที่จะได้ถูกชี้เข้าไปในตัวแปรนั้นๆ

อ่าน json.Unmarshal เพิ่มเติมที่ https://golang.org/pkg/encoding/json/#Unmarshal

ทดสอบ run code ที่ https://play.golang.org/p/vILOKPvoKm0

ในบรรทัดสุดท้ายทดสอบ print ผลลัพธ์ออกมาอ่าน จะเห็นว่าค่า name จะอยู่ที่ p1.Name เท่ากับ Atom ค่า age อยู่ที่ p1.Age เท่ากับ 5

เกร็ดเล็กน้อย 1. สังเกตนะครับว่าภายใน Struct ของผมใช้เป็นตัวใหญ่ตัวแรกเนื่องจาก field ที่เป็นตัวใหญ่เท่านั้นที่จะถูก Export ไปข้างนอกได้ ในอีกความหมายก็คือ package อื่นสามารถ อ่านค่าได้

เกร็ดเล็กน้อย 2. เราสามารถ Unmarshal json ได้ลึกหรือโครงสร้างยังไงก็ได้ตามที่เราต้องการ แต่ต้องออกแบบให้ตรงกันทั้งตัวส่งและตัวรับ เช่น ตัวส่งเป็น array json ตัวรับก็ต้องเป็น array เช่นกัน

// This is JSON input example
myJsonString := `[
{
"name": "Atom",
"age": 5
}
]`
var p1 []Person
json.Unmarshal([]byte(myJsonString), &p1)

หรือ Embedded objects (Struct ซ้อนเข้าไปอีก) https://play.golang.org/p/ROdywS5gYB4 <- ลองเล่น

// Person is an object to collect person data
type Person struct {
Name string
Age int
Bmi BMI
}
// BMI is an object that collect BMI of person
type BMI struct {
Height float64
Weight float64
}
// This is JSON input example
myJsonString := `[
{
"name": "Atom",
"age": 5,
"bmi": {
height: 170.5,
weight: 60.5
}
}
]`
var p1 []Person
json.Unmarshal([]byte(myJsonString), &p1)

เกร็ดเล็กน้อย 3. เราสามารถ custom ชื่อ field ตามที่เราต้องการได้ แต่ Key ใน JSON string ต้องตรงกันด้วยนะ https://play.golang.org/p/shV8GJBDvAm <- ลองเล่น

type Person struct {
Name string `json:"personName"`
Age int `json:"personAge"`
}
// This is JSON input example
myJsonString := `[
{
"personName": "Atom",
"personAge": 5
}
]`

Unstructured data

วิธีนี้ก็สมชื่ออีกเช่นกัน ซึ่งก็คือ ข้อมูลที่มีโครงสร้างไม่ชัดเจน ตัวอย่างเช่น ไม่ทราบ property ของ json input ที่ส่ง เข้ามาว่าจะมีลักษณะเป็นอะไร เป็น string, int หรือ float64 สำหรับในกรณีนี้ ก็จะเห็นได้ชัดเลยว่า ไม่สามารถใช้ struct ที่เราสร้างเองได้ เพราะเราไม่รู้โครงสร้างข้อมูล เราจึงต้องใช้สิ่งที่เรียกว่า map เข้ามาช่วย และ interface{} สำหรับค่าที่เป็นอะไรก็ได้ เนื่องจากไม่ทราบ property ของ ค่าใน json

var example map[string]interface{}

map คือการเก็บตัวแปรที่อยู่ในรูปแบบ key และ value โดยในที่นี้ map[string]interface{} Key เป็นประเภท string และ value เป็น interface{} ซึ่งเป็นค่าอะไรก็ได้

// This is JSON example
ex := `{
"headset": "BeBirdNok",
"version": 999,
"price": 199.99
}`
var result map[string]interface{}
json.Unmarshal([]byte(ex), &result)

https://play.golang.org/p/UhP04ROemVB <- ลองเล่น

จบแล้วกับการ Parse JSON ต่อไปจะมาอธิบายเรื่องอะไรอีกต้องตามอ่านนะครับถึงจะรู้

--

--

Visarut Junsone
Lazy-Dev

I’m Full-Stack Developer. ReactJS Golang C# Javascript C++ PHP and learning a lot more. Not lazy as it name. “Lazy-Dev”