Go語言的json包提供了一種將結(jié)構(gòu)體數(shù)據(jù)格式化為JSON的方法- json.Marshaler 接口。
在使用json.Marshal函數(shù)將數(shù)據(jù)進行格式化時,如果數(shù)據(jù)中存在自定義類型,程序會嘗試將自定義類型轉(zhuǎn)換為默認格式的類型,例如將time.Time類型轉(zhuǎn)換成RFC 3339 格式字符串。然而,如果存在一些自定義的類型無法被默認轉(zhuǎn)換或需要我們自己定義格式,json.Marshaler就可以派上用場。
type Person struct { Name string Age int Gender gender Address *Address } type gender int // 實現(xiàn)json.Marshaler接口 func (g gender) MarshalJSON() ([]byte, error) { switch g { case male, female: return []byte(fmt.Sprintf("\"%s\"", g.String())), nil default: return nil, fmt.Errorf("invalid gender value %d", g) } } type Address struct { Province string City string } // 實現(xiàn)json.Marshaler接口 func (a *Address) MarshalJSON() ([]byte, error) { return []byte(fmt.Sprintf("\"%s,%s\"", a.Province, a.City)), nil } const ( male gender = iota female ) func main() { p := Person{ Name: "Bob", Age: 28, Gender: male, Address: &Address{"北京市", "北京市"}, } b, err := json.Marshal(p) if err != nil { log.Fatal(err) } fmt.Printf("json string: %s\n", string(b)) }
在上面的例子中,我們自定義了gender和Address兩個類型,并在它們中間分別實現(xiàn)了MarshalJSON方法,以便滿足我們的特殊需求。在main函數(shù)中,我們創(chuàng)建了一個Person類型的實例并嘗試使用json.Marshal函數(shù)將其轉(zhuǎn)換為JSON。由于Person類型中包含自定義類型gender和Address,當進行格式化時,程序會自動調(diào)用它們中的MarshalJSON方法,實現(xiàn)自定義格式化之后,最后輸出的JSON字符串是:
{"Name":"Bob","Age":28,"Gender":"男","Address":"北京市,北京市"}
可以看到,返回的JSON字符串符合我們所期望的格式。