Custom JSON Marshalling&UnMarshalling in Go

本文介绍了如何通过标签自定义Go中JSON序列化的方式,如使用`json:",omitempty"`来忽略空值。同时,通过实现`MarshalJSON`和`UnmarshalJSON`方法,可以完全控制类型在序列化和反序列化过程中的行为。当需要临时为结构体添加字段时,可以通过创建临时类型并嵌入原类型来实现,避免无限循环的方法是使用别名。这种技巧同样适用于实现`UnmarshalJSON`方法。" 83068056,7912310,SQL面试经典题目解析,"['SQL查询', '数据库', '数据分析']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

We know that through tags, we can conditionally customize the way of Go JSON serialization, such as json:",omitempty".
We know that through tags, we can conditionally customize the way of Go JSON serialization, such as json:",omitempty". When the value of the field is empty, we can not include this value in the serialized data. And json: “-” can be directly not serialized by JSON, if you want to be serialized key-, you can set the tag to json: “-,” and add a comma.If you implement MarshalJSON() ([]byte, error) and UnmarshalJSON(b []byte) error methods for the type, then this type will use your customized method during serialization and deserialization.
These are our commonly used setting techniques.

If you want to add a field to a struct temporarily, you can create a type temporarily and implement it by embedding the original type. He is not the same as the technique introduced in the article JSON and struct composition in Go. In the article JSON and struct composition in Go, a new type is created by embedding. You need to use this new type when serializing and deserializing. The method in this translation is to painlessly change the MarshalJSON method of the original type. Using Alias ​​to avoid recursive analysis is indeed a very clever way.
The following is the original text:
Go’s encoding/json package makes it really easy to marshal structs to JSON data.

package main

import (
	"encoding/json"
	"os"
	"time"
)

type MyUser struct {
	ID       int64     `json:"id"`
	Name     string    `json:"name"`
	LastSeen time.Time `json:"lastSeen"`
}

func main() {
	_ = json.NewEncoder(os.Stdout).Encode(
		&MyUser{1, "Ken", time.Now()},
	)
}

Output

{"id":1,"name":"Ken","lastSeen":"2009-11-10T23:00:00Z"}

But what if we want to change how one of the field values are displayed? For example, say I wanted LastSeen to be a unix timestamp.

The simple solution is to introduce another auxiliary struct and populate it with the correctly formatted values in the MarshalJSON method.

func (u *MyUser) MarshalJSON() ([]byte, error) {
	return json.Marshal(&struct {
		ID       int64  `json:"id"`
		Name     string `json:"name"`
		LastSeen int64  `json:"lastSeen"`
	}{
		ID:       u.ID,
		Name:     u.Name,
		LastSeen: u.LastSeen.Unix(),
	})
}

This works, but it can get cumbersome when there are lots of fields. It would be nice if we could embed the original struct into the auxiliary struct and have it inherit all the fields that do not need to be changed.

func (u *MyUser) MarshalJSON() ([]byte, error) {
	return json.Marshal(&struct {
		LastSeen int64 `json:"lastSeen"`
		*MyUser
	}{
		LastSeen: u.LastSeen.Unix(),
		MyUser:   u,
	})
}

The problem here is that the auxiliary struct will also inherit the original’s MarshalJSON method, causing it to go into an infinite loop. The solution is to alias the original type. This alias will have all the same fields, but none of the methods.

func (u *MyUser) MarshalJSON() ([]byte, error) {
	type Alias MyUser
	return json.Marshal(&struct {
		LastSeen int64 `json:"lastSeen"`
		*Alias
	}{
		LastSeen: u.LastSeen.Unix(),
		Alias:    (*Alias)(u),
	})
}

The same technique can be used for implementing an UnmarshalJSON method.

func (u *MyUser) UnmarshalJSON(data []byte) error {
	type Alias MyUser
	aux := &struct {
		LastSeen int64 `json:"lastSeen"`
		*Alias
	}{
		Alias: (*Alias)(u),
	}
	if err := json.Unmarshal(data, &aux); err != nil {
		return err
	}
	u.LastSeen = time.Unix(aux.LastSeen, 0)
	return nil
}

reference :
link
link
link
link
link

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值