自定义序列化和反序列化
可以实现 json.Marshaler 和 json.Unmarshaler 自定义json的序列化和反序列化
type Tags []string
func (t Tags) MarshalJSON() ([]byte, error) {
return []byte(strconv.Quote(strings.Join(t, ","))), nil
}
func (t *Tags) UnmarshalJSON(b []byte) error {
b = bytes.Trim(b, `"`)
*t = strings.Split(string(b), ",")
return nil
}
func TestTags(t *testing.T) {
tags := Tags([]string{"美丽", "性感", "迷人"})
b, _ := json.Marshal(tags)
if `"美丽,性感,迷人"` != string(b) {
t.Error("自定义序列化出错")
}
json.Unmarshal([]byte(`"性感,美丽,迷人"`), &tags)
if tags[0] != "性感" || tags[1] != "美丽" || tags[2] != "迷人" {
t.Error("自定义反序列化出错")
}
}
struct 的 tag
go结构体的字段经常用tag来扩展功能,比如json,我们也可以利用reflect包自定义tag解析(gorm利用结构体tag声明字段和数据库的映射)
type Product struct {
Name string // 不写json tag,默认映射为Name
RealName string `json:"-"` // 表示不序列化,也不反序列化
Price float64 `json:"price,string"` // string 可以把 "16.56" 映射为 float64,会把 13.56 输出为 "13.56"
Count int `json:"count,omitempty"` // omitempty 表示零值不输出
}
func TestProduct(t *testing.T) {
p1 := Product{
Name: "iPhone",
RealName: "iPhone 8 Pro",
Price: 13.15,
Count: 0,
}
b, _ := json.Marshal(&p1)
if `{"Name":"iPhone","price":"13.15"}` != string(b) {
t.Error("Product 序列化失败")
}
}
不序列化 time.Time
使用time.Time nil指针表示不序列化json,防止输出非法格式的时间
func TestIgnoreNilTime(t *testing.T) {
// 使用nil表示不输出时间
user1 := struct {
UserId int `json:"userId"`
CreatedAt *time.Time `json:"createdAt,omitempty"`
}{
UserId: 100019,
}
b, _ := json.Marshal(&user1)
if `{"userId":100019}` != string(b) {
t.Error("")
}
}
忽略字段和格式化字段
type User struct {
UserId int `json:"userId"`
Phone string `json:"phone"`
Password string `json:"password"`
Money float64 `json:"money"`
}
func TestStructEmbedded(t *testing.T) {
user1 := User{
UserId: 100019,
Phone: "13112120001",
Password: "abc123",
Money: 123.56123,
}
user2 := struct {
User // 嵌入 User 结构
Phone string `json:"phone"` // 覆盖 User 结构中的 Phone 实现隐藏手机号
Password string `json:"password,omitempty"` // 不输出密码
Money string `json:"money"` // 会覆盖 User 结构中的 Money
}{
User: user1,
Phone: filterPhone(user1.Phone),
Money: fmt.Sprintf("%.2f", user1.Money),
}
b, _ := json.Marshal(&user2)
if `{"userId":100019,"phone":"131****0001","money":"123.56"}` != string(b) {
t.Error("")
}
}
func filterPhone(phone string) string {
if len(phone) != 11 {
return ""
}
return phone[:3] + "****" + phone[7:]
}
结构体嵌入用来共用一些通用字段
结构体复制
简单结构使用手动复制就可以,复杂结构可用开源库来复制
比如 https://github.com/jinzhu/copier
结构体复制时,防止浅拷贝问题
结构体直接复制时,里面的指针或者slice等会指向同一份内存数据,修改时需要注意。
可以采用 [https://github.com/jinzhu/copier]https://github.com/jinzhu/copier 进行深拷贝
结构体嵌入和 json 自定义一起使用,可以在序列化和反序列化时做转换
type UserProfile struct {
Nickname string `json:"nickname"`
IdCardNo string `json:"idCardNo"`
}
func (u UserProfile) MarshalJSON() ([]byte, error) {
type UserProfileAlias UserProfile
u1 := struct {
UserProfileAlias
IdCardNo string `json:"idCardNo"`
}{
UserProfileAlias: UserProfileAlias(u),
IdCardNo: "****",
}
b, _ := json.Marshal(&u1)
return b, nil
}
type Liver struct {
UserProfile *UserProfile `json:"userProfile"`
}
func TestLiverJson(t *testing.T) {
liver := Liver{
UserProfile: &UserProfile{
Nickname: "娜娜丫头",
IdCardNo: "123456",
},
}
b, _ := json.Marshal(&liver)
if `{"userProfile":{"nickname":"娜娜丫头","idCardNo":"****"}}` != string(b) {
t.Error("结构体嵌入和json自定义出错")
}
}
标签:string,自定义,json,Golang,JSON,func,Go,序列化,struct
From: https://www.cnblogs.com/goallin/p/17612418.html