Compiled fromCustom JSON Marshalling in Go。
Preface
We know that through tags, custom Go JSON serialization can be implemented conditionally, 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 the MarshalJSON() ([]byte, error) and UnmarshalJSON(b []byte) error methods for the type, then this type will use your customized method when serializing and deserializing it.
These are the settings we use frequently.
If you want to add a field to a struct temporarily, you can use the skills of this translation to temporarily create a type, which can be implemented by embedding the original type. He andJSON and struct composition in GoThe techniques introduced in the article are different (the translation and jsoniter-go extension can be read in Tao's articleSome tips for using JSON in Golang). JSON and struct composition in Go article creates a new type through 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, and to use the Alias method to avoid recursive parsing, which is indeed a very clever way.
The following is the translation
Go's encoding/json serializes strcut to JSON data:
package main import ( "encoding/json" "os" "time" ) type MyUser struct { ID int64 `json:"id"` Name string `json:"name"` LastSeen `json:"lastSeen"` } func main() { _ = ().Encode( &MyUser{1, "Ken", ()}, ) }
The results of serialization
{"id":1,"name":"Ken","lastSeen":"2009-11-10T23:00:00Z"}
But what do we do if we want to change the display result of a field? For example, we want to display LastSeen as a unix timestamp.
The easiest way is to introduce another auxiliary struct, which is used in MarshalJSON to format correctly:
func (u *MyUser) MarshalJSON() ([]byte, error) { return (&struct { ID int64 `json:"id"` Name string `json:"name"` LastSeen int64 `json:"lastSeen"` }{ ID: , Name: , LastSeen: (), }) }
Of course there is no problem doing this, but it will be troublesome if there are many fields. It would be great if we can embed the original struct into the new struct and let it inherit all fields that do not need to be changed:
func (u *MyUser) MarshalJSON() ([]byte, error) { return (&struct { LastSeen int64 `json:"lastSeen"` *MyUser }{ LastSeen: (), MyUser: u, }) }
But wait, the problem is that this auxiliary struct will also inherit the MarshalJSON method of the original struct, which will cause this method to enter an infinite loop and finally stack overflow.
The solution is to give an alias to the original type. The alias will have all the fields of the original struct, but it will not be inherited:
func (u *MyUser) MarshalJSON() ([]byte, error) { type Alias MyUser return (&struct { LastSeen int64 `json:"lastSeen"` *Alias }{ LastSeen: (), Alias: (*Alias)(u), }) }
The same technique can also be applied to the UnmarshalJSON method:
func (u *MyUser) UnmarshalJSON(data []byte) error { type Alias MyUser aux := &struct { LastSeen int64 `json:"lastSeen"` *Alias }{ Alias: (*Alias)(u), } if err := (data, &aux); err != nil { return err } = (, 0) return nil }
The above is the detailed content of the translation of the custom Go Json serialization method. For more information about Go Json serialization customization, please follow my other related articles!