自定义 JSON 序列化是 Golang 开发中非常有用的技术。 通过自定义序列化规则,我们可以将 Golang 程序数据结构转为 JSON 字符串或者将 JSON 字符串转为 Golang 数据结构,使得数据交互操作更加简单方便。本文将详细介绍如何在Golang中自定义JSON 序列化。

1.自定义JSON序列化

1.1 json.Marshal()

要实现自定义序列化,我们需要使用到 json 包中提供的 Marshal 方法。 该方法的中文注释为:“Marshal 函数返回 v 的 JSON 编码。

对于自定义类型,我们需要实现 JSON 的序列化过程。 我们通常可以通过给结构体增加 JSON 标签来标示每个字段对应 JSON 中的什么名称。 可以使用:作为标签后面字段的别名。

同时,我们还需要在结构体中增加 MarshalJSON 方法来实现序列化过程。 在 MarshallJSON 方法中,我们需要将结构体中的字段逐一转为正确的 JSON 格式。例如,string 类型需要被包含在双引号中。

1.2 实现示例1

首先,让我们看一个简单的示例。在下面的代码中,我们定义了一个 struct 类型,它包含了内置类型的字段:

type Student struct {
    Name   string
    Age    int
    Gender string
}

假设我们希望将该结构体序列化为 JSON 中的 name 字段,而非字段名 Name,我们可以使用以下的代码实现:

type Student struct {
    Name   string `json:"name"`
    Age    int    `json:"age"`
    Gender string `json:"gender"`
}

func (s *Student) MarshalJSON() ([]byte, error) {
    buffer := bytes.NewBufferString(`{"name":`)
    b, err := json.Marshal(s.Name)
    if err != nil {
        return nil, err
    }
    buffer.Write(b)
    buffer.WriteString(`, "age":`)
    b, err = json.Marshal(s.Age)
    if err != nil {
        return nil, err
    }
    buffer.Write(b)
    buffer.WriteString(`, "gender":`)
    b, err = json.Marshal(s.Gender)
    if err != nil {
        return nil, err
    }
    buffer.Write(b)
    buffer.WriteString(`}`)
    return buffer.Bytes(), nil
}

在 上述代码中,我们使用了一个叫做 buffer 的 bytes.Buffer 对象,用于输出 JSON 字符串。 在 MarshalJSON 中,我们排版了一页代码,实现了序列化过程。

1.3 实现示例2

让我们再来看一个稍微复杂一点的示例。 在下面的代码中,我们定义了一个 struct 类型 :

type Programmer struct {
    Name         string
    Age          int
    LanguageList []string
}

与第一个示例不同,这次我们有一个 string 类型的列表字段。 这意味着,我们需要特别地对它序列化。

在实现上,我们需要借助其他的 struct 类型来表示这个列表。 在该 struct 中,我们可以使用 []byte 类型来表示 string 类型的列表。 参考我们的代码:

type Programmer struct {
    Name         string   `json:"name"`
    Age          int      `json:"age"`
    LanguageList []string `json:"language_list"`
}

type ProgrammerJSON struct {
    Name         string        `json:"name"`
    Age          int           `json:"age"`
    LanguageList []byte `json:"language_list"`
}

func (p *Programmer) MarshalJSON() ([]byte, error) {
    pj := &ProgrammerJSON{
        Name: p.Name,
        Age: p.Age,
        LanguageList: []byte(`["` + strings.Join(p.LanguageList, `","`) + `"]`),
    }
    return json.Marshal(pj)
}
json:"language_list"
`,
2.Marshaller和Unmarshaller

2.1 实现示例

Golang 在 json 包中提供了三个内置类型,分别为 JSONEncoder,JSONDecoder 和 JSONUnmarshaler。 我们可以简单地通过实现这三个接口来实现 JSON 序列化和反序列化。 以下是一个简单的示例,其中 T 类型中仅包含了一个 string 字段。

type T struct {
    ID   int64 `json:"id"`
    Name string `json:"name"`
}

func (t *T) MarshalJSON() ([]byte, error) {
    return json.Marshal(&struct {
        ID   int64  `json:"id"`
        Name string `json:"name"`
    }{
        ID:   t.ID,
        Name: t.Name,
    })
}

func (t *T) UnmarshalJSON(data []byte) error {
    tmp := &struct {
        ID   int64  `json:"id"`
        Name string `json:"name"`
    }{}
    err := json.Unmarshal(data, tmp)
    if err != nil {
        return err
    }
    t.ID = tmp.ID
    t.Name = tmp.Name
    return nil
}

在 上述代码中,我们实现了 MarshalJSON 和 UnmarshalJSON 方法,用于将 T 类型序列化为 JSON 格式和从 JSON 格式反序列化为 T 类型。 我们只需要通过这种方式对自定义类型进行实现,就可以简单快捷地实现 JSON 序列化和反序列化。