MST

星途 面试题库

面试题:Go语言自定义JSON序列化与反序列化行为

假设你有一个复杂的自定义数据类型,该类型内部包含一些特殊的逻辑,常规的JSON序列化与反序列化方式无法满足需求。请说明如何通过实现`json.Marshaler`和`json.Unmarshaler`接口来自定义该数据类型的JSON序列化与反序列化行为,并且在反序列化时进行数据校验和预处理,给出完整的代码示例和详细解释。
27.4万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

以下是一个Go语言的示例,展示如何通过实现json.Marshalerjson.Unmarshaler接口来自定义复杂数据类型的JSON序列化与反序列化行为,并在反序列化时进行数据校验和预处理:

package main

import (
	"encoding/json"
	"fmt"
	"strings"
)

// 定义自定义数据类型
type CustomType struct {
	Value string
}

// 实现json.Marshaler接口的MarshalJSON方法
func (ct CustomType) MarshalJSON() ([]byte, error) {
	// 自定义序列化逻辑,这里简单示例将Value字段转成大写
	return json.Marshal(strings.ToUpper(ct.Value))
}

// 实现json.Unmarshaler接口的UnmarshalJSON方法
func (ct *CustomType) UnmarshalJSON(data []byte) error {
	var value string
	err := json.Unmarshal(data, &value)
	if err != nil {
		return err
	}

	// 数据校验,例如确保Value不为空
	if value == "" {
		return fmt.Errorf("value cannot be empty")
	}

	// 预处理,例如将Value转成小写
	ct.Value = strings.ToLower(value)
	return nil
}

func main() {
	// 示例使用
	original := CustomType{Value: "hello"}

	// 序列化
	serialized, err := json.Marshal(original)
	if err != nil {
		fmt.Println("Marshal error:", err)
		return
	}
	fmt.Println("Serialized:", string(serialized))

	// 反序列化
	var deserialized CustomType
	err = json.Unmarshal(serialized, &deserialized)
	if err != nil {
		fmt.Println("Unmarshal error:", err)
		return
	}
	fmt.Println("Deserialized:", deserialized.Value)
}

代码解释

  1. 自定义数据类型:定义了一个名为CustomType的结构体,它包含一个string类型的字段Value
  2. 实现json.Marshaler接口
    • MarshalJSON方法负责将CustomType实例转换为JSON格式的字节切片。在这个示例中,我们将Value字段转换为大写字母后再进行JSON序列化。
  3. 实现json.Unmarshaler接口
    • UnmarshalJSON方法负责将JSON格式的字节切片转换回CustomType实例。
    • 首先,使用json.Unmarshal将JSON数据解析到一个临时的string变量中。
    • 然后进行数据校验,这里检查Value是否为空,如果为空则返回错误。
    • 最后进行预处理,将Value转换为小写字母,并赋值给CustomType实例的Value字段。
  4. 主函数
    • 创建一个CustomType的实例并赋值。
    • 对实例进行序列化,并打印序列化后的结果。
    • 将序列化后的结果反序列化回CustomType实例,并打印反序列化后的结果。在反序列化过程中,会自动调用我们实现的UnmarshalJSON方法进行数据校验和预处理。