- vừa được xem lúc

Struct Tags trong Go - làm việc với Json

0 0 3

Người đăng: Xuân Nguyễn

Theo Viblo Asia

Mình vừa đọc một bài viết hay về Struct Tags trong Golang nên mình muốn note ngay những ý quan trọng mà mình chưa biết xuống đây.

Json trong Go

Go cung cấp một standard library làm việc với json mạnh mẽ: encoding/json và struct tags tăng cường khả năng đó bằng cách cho phép tuỳ chỉnh cách dữ liệu được chuyển đổi từ data trong Go thành json và ngược lại. Trong encoding/json, ta quan tâm đến 2 hàm chính:

  • Mashal: chuyển dữ liệu Go thành Json
  • Unmarshal: ngược lại với marshal, chuyển Json thành dữ liệu trong Go. Struct là kiểu dữ liệu map tự nhiên với json nên thường được sử dụng để chuyển đổi thành Json và ngược lại. Lấy ví dụ ta có chương trình:
type Person struct { Name string Age int
} func main() { p := Person{Name: "Alice", Age: 30} jsonData, err := json.Marshal(p) if err != nil { fmt.Println("Error marshalling to JSON:", err) return } fmt.Println(string(jsonData))
}

Kết quả in ra:

{"Name":"Alice","Age":30}

Ta thấy các field Name, Age trong struct map tự nhiên với các key Name, Age trong jsonData.

Struct Tags

Struct Tags cho phép tuỳ chỉnh cách dữ liệu được marshal/unmarshal giữa Go data và Json. Cũng ví dụ trên, ta muốn các key khi được chuyển thành json phải được viết thường, ta thêm các tag json:key_name trong phần khai báo các field của struct:

type Person struct { Name string `json:"name"` Age int `json:"age"`
}

Chạy lại chương trình, ta được:

{"name":"Alice","age":30}

Các tag json:"name",json:"age" chỉ ra rằng việc map field Name trong struct sẽ thành key name trong json khi marshal và ngược lại. Điều này giúp tuỳ biến cách các key được map:

package main import ( "encoding/json" "fmt"
) type Person struct { Name string `json:"ten"` Age int `json:"tuoi"` Addr string `json:"dia_chi"`
} func main() { p := Person{Name: "Alice", Age: 30, Addr: "123 Main St"} jsonData, err := json.Marshal(p) if err != nil { fmt.Println("Error marshalling to JSON:", err) return } fmt.Println(string(jsonData))
}

Chuyển struct tiếng anh thành json tiếng việt luôn.

{"ten":"Alice","tuoi":30,"dia_chi":"123 Main St"}

Omitting Fields

Field có tag json:"-" bị bỏ qua khi marshal (tất nhiên là cũng sẽ không có key nào được map thành field này khi unmarshal).

type Person struct { Name string `json:"ten"` Age int `json:"tuoi"` Addr string `json:"-"`
}
{"ten":"Alice","tuoi":30} //Không có field Addr

Omitting Empty Fields

Tag này dùng để bỏ qua field/key có zero value. Syntax `json:"key_name,omitempty""

type Person struct { Name string `json:"ten,omitempty"` Age int `json:"tuoi,omitempty"` Addr string `json:"dia_chi"`
} func main() { p := Person{} jsonData, err := json.Marshal(p) if err != nil { fmt.Println("Error marshalling to JSON:", err) return } fmt.Println(string(jsonData)) }

Kết quả

{"dia_chi":""}

Field Name và Age có tag omitempty nên bị bỏ qua khi marshal json, Addr không có omitempty nên vẫn được giữ lại với value "".

Tạo struct hay được suggest bởi các AI assistence và tag omitempty rất thường được thêm vào một cách tự động, lưu ý hãy sử dụng tag này một cách cẩn trọng, chỉ sử dụng với những field nào nếu có value là zero value thì bỏ qua được.

Optional Fields with Pointers

Chỗ này để phân biệt zero value và unset field, dùng con trỏ cho field đó thôi. Cụ thể hơn xíu, trường hợp Alice 0 tuổi thì khi 0 được gán cho Age, Age = 0 bị hiểu là zero value và khi kết hợp với tag "omitempty", key "tuoi" sẽ không tồn tại trong json. Nhằm tránh tình trạng trên, ta dùng Age là con trỏ *int.

Marshal với embedding struct

type MetaData struct { CreatedAt string `json:"created_at,omitempty"` UpdatedAt string `json:"updated_at,omitempty"`
} type Person struct { Name string `json:"ten,omitempty"` Age int `json:"tuoi,omitempty"` MetaData //Cái này gọi là embedded field
} func main() { var user Person = Person{ Name: "Alice", Age: 30, MetaData: MetaData{ CreatedAt: "2023-10-01", UpdatedAt: "2023-10-10", }, } jsonData, err := json.Marshal(user) if err != nil { fmt.Println("Error:", err) return } err = json.Unmarshal(jsonData, &user) if err != nil { fmt.Println("Error:", err) return } fmt.Println(string(jsonData)) }
{"ten":"Alice","tuoi":30,"created_at":"2023-10-01","updated_at":"2023-10-10"}

Các filed của MetaData (là struct được nhúng trong Person) khi marshal sẽ nằm cùng cấp các các filed trong Person.

Error handling

Các operations của json hay xảy ra lỗi về tính valid của json, kiểu dữ liệu,... Để catch và handle các lỗi, bạn nên kiểm tra error sau khi thực hiện các operations:

	err := json.Unmarshal(jsonData, &user) if err != nil { fmt.Println("Error:", err) return }

Bình luận

Bài viết tương tự

- vừa được xem lúc

gRPC - Nó là gì và có nên sử dụng hay không?

Nhân một ngày rảnh rỗi, mình ngồi đọc lại RPC cũng như gRPC viết lại để nhớ lâu hơn. Vấn đề là gì và tại sao cần nó .

0 0 161

- vừa được xem lúc

Embedded Template in Go

Getting Start. Part of developing a web application usually revolves around working with HTML as user interface.

0 0 73

- vừa được xem lúc

Tạo Resful API đơn giản với Echo framework và MySQL

1. Giới thiệu.

0 0 84

- vừa được xem lúc

Sử dụng goquery trong golang để crawler thông tin các website Việt Nam bị deface trên mirror-h.org

. Trong bài viết này, mình sẽ cùng mọi người khám phá một package thu thập dữ liệu có tên là goquery của golang. Mục tiêu chính của chương trình crawler này sẽ là lấy thông tin các website Việt Nam bị deface (là tấn công, phá hoại website, làm thay đổi giao diện hiển thị của một trang web, khi người

0 0 265

- vừa được xem lúc

Tạo ứng dụng craw dữ liệu bing với Golang, Mysql driver

Chào mọi người . Lâu lâu ta lại gặp nhau 1 lần, để tiếp tục series chia sẻ kiến thức về tech, hôm nay mình sẽ tìm hiểu và chia sẻ về 1 ngôn ngữ đang khá hot trong cộng đồng IT đó là Golang.

0 0 104

- vừa được xem lúc

Golang: Rest api and routing using MUX

Routing with MUX. Let's create a simple CRUD api for a blog site. # All . GET articles/ .

0 0 84