面试题答案
一键面试以下是一个Go语言的示例,展示如何通过实现json.Marshaler
和json.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)
}
代码解释
- 自定义数据类型:定义了一个名为
CustomType
的结构体,它包含一个string
类型的字段Value
。 - 实现
json.Marshaler
接口:MarshalJSON
方法负责将CustomType
实例转换为JSON格式的字节切片。在这个示例中,我们将Value
字段转换为大写字母后再进行JSON序列化。
- 实现
json.Unmarshaler
接口:UnmarshalJSON
方法负责将JSON格式的字节切片转换回CustomType
实例。- 首先,使用
json.Unmarshal
将JSON数据解析到一个临时的string
变量中。 - 然后进行数据校验,这里检查
Value
是否为空,如果为空则返回错误。 - 最后进行预处理,将
Value
转换为小写字母,并赋值给CustomType
实例的Value
字段。
- 主函数:
- 创建一个
CustomType
的实例并赋值。 - 对实例进行序列化,并打印序列化后的结果。
- 将序列化后的结果反序列化回
CustomType
实例,并打印反序列化后的结果。在反序列化过程中,会自动调用我们实现的UnmarshalJSON
方法进行数据校验和预处理。
- 创建一个