package main
import (
"encoding/json"
"fmt"
"time"
)
// 自定义时间格式结构体
type CustomTime struct {
time.Time
}
// 实现MarshalJSON方法,用于自定义JSON编码格式
func (ct CustomTime) MarshalJSON() ([]byte, error) {
// 自定义时间格式
formattedTime := ct.Time.Format("2006-01-02 15:04:05")
return []byte(`"` + formattedTime + `"`), nil
}
// 实现UnmarshalJSON方法,用于自定义JSON解码格式
func (ct *CustomTime) UnmarshalJSON(b []byte) error {
var err error
// 去除双引号
s := string(b[1 : len(b)-1])
// 解析时间
ct.Time, err = time.Parse("2006-01-02 15:04:05", s)
return err
}
// 嵌套结构体
type InnerStruct struct {
ID int
Name string
Time CustomTime
}
// 外层结构体
type OuterStruct struct {
Inner InnerStruct
}
// 主函数
func main() {
// 初始化切片
dataSlice := []OuterStruct{
{Inner: InnerStruct{ID: 1, Name: "Alice", Time: CustomTime{Time: time.Now()}}},
{Inner: InnerStruct{ID: 2, Name: "Bob", Time: CustomTime{Time: time.Now()}}},
}
// 转换为JSON数据
jsonData, err := json.MarshalIndent(dataSlice, "", " ")
if err != nil {
fmt.Println("Marshal error:", err)
return
}
fmt.Println("JSON data:\n", string(jsonData))
// 从JSON数据转换回切片
var newSlice []OuterStruct
err = json.Unmarshal(jsonData, &newSlice)
if err != nil {
fmt.Println("Unmarshal error:", err)
return
}
fmt.Println("New slice:", newSlice)
}
原理和关键技术点解释
- 自定义JSON编码格式:
- 为了实现时间字段的特定格式化输出,我们定义了一个
CustomTime
结构体,它嵌入了Go语言标准库中的time.Time
结构体。
- 通过为
CustomTime
结构体实现MarshalJSON
方法,我们可以控制该结构体在转换为JSON时的格式。在MarshalJSON
方法中,我们使用time.Format
函数将时间格式化为指定的字符串,然后再封装成JSON格式的字节切片返回。
- 自定义JSON解码格式:
- 同样为
CustomTime
结构体实现UnmarshalJSON
方法,用于在从JSON数据转换回Go结构体时,解析自定义格式的时间字符串。在UnmarshalJSON
方法中,我们先去除JSON字符串的双引号,然后使用time.Parse
函数将字符串解析为time.Time
类型。
- 嵌套结构体处理:
- 我们定义了
InnerStruct
和OuterStruct
两个结构体,InnerStruct
包含了需要自定义JSON编码格式的时间字段,OuterStruct
嵌套了InnerStruct
。
- 当使用
json.Marshal
和json.Unmarshal
时,Go语言的JSON包会递归地处理嵌套结构体,自动调用我们为CustomTime
定义的MarshalJSON
和UnmarshalJSON
方法。
json.Marshal
和json.Unmarshal
:
json.Marshal
函数用于将Go语言的数据结构转换为JSON格式的字节切片。json.MarshalIndent
函数则可以格式化输出,使JSON数据更易读。
json.Unmarshal
函数用于将JSON格式的字节切片转换回Go语言的数据结构。在使用时,需要传入指向目标数据结构的指针。