插件窝 干货文章 Go语言JSON解析:自定义UnmarshalJSON后字段丢失,如何解决?

Go语言JSON解析:自定义UnmarshalJSON后字段丢失,如何解决?

字段 UnmarshalJSON 解析 Field 779    来源:    2025-03-15

在Go语言中,当你为某个结构体自定义了 UnmarshalJSON 方法后,可能会出现字段丢失的问题。这通常是因为在自定义的 UnmarshalJSON 方法中,你没有正确处理所有的字段,导致部分字段没有被正确解析。

问题分析

假设你有以下结构体:

type MyStruct struct {
    Field1 string `json:"field1"`
    Field2 int    `json:"field2"`
}

你为 MyStruct 自定义了 UnmarshalJSON 方法:

func (m *MyStruct) UnmarshalJSON(data []byte) error {
    // 只解析 Field1
    var temp struct {
        Field1 string `json:"field1"`
    }
    if err := json.Unmarshal(data, &temp); err != nil {
        return err
    }
    m.Field1 = temp.Field1
    return nil
}

在这个例子中,Field2 没有被解析,因此在反序列化后,Field2 的值会丢失。

解决方案

要解决这个问题,你需要在自定义的 UnmarshalJSON 方法中处理所有的字段。你可以使用一个临时的结构体来解析所有的字段,然后再将这些字段赋值给目标结构体。

func (m *MyStruct) UnmarshalJSON(data []byte) error {
    // 使用临时结构体解析所有字段
    var temp struct {
        Field1 string `json:"field1"`
        Field2 int    `json:"field2"`
    }
    if err := json.Unmarshal(data, &temp); err != nil {
        return err
    }

    // 将解析后的字段赋值给目标结构体
    m.Field1 = temp.Field1
    m.Field2 = temp.Field2

    return nil
}

更通用的解决方案

如果你有多个字段,或者不想手动处理每个字段,可以使用 json.Unmarshalmap[string]interface{} 方式来解析所有字段,然后再根据需要处理这些字段。

func (m *MyStruct) UnmarshalJSON(data []byte) error {
    // 使用 map 解析所有字段
    var temp map[string]interface{}
    if err := json.Unmarshal(data, &temp); err != nil {
        return err
    }

    // 处理 Field1
    if field1, ok := temp["field1"].(string); ok {
        m.Field1 = field1
    }

    // 处理 Field2
    if field2, ok := temp["field2"].(float64); ok {
        m.Field2 = int(field2)
    }

    return nil
}

总结

在自定义 UnmarshalJSON 方法时,确保你处理了所有的字段,否则会导致字段丢失。你可以使用临时结构体或 map[string]interface{} 来解析所有字段,然后再将这些字段赋值给目标结构体。这样可以确保所有字段都被正确解析和赋值。