我的情况很不正常。我希望MarshalJSON有条件地省略结构字段。在下面的示例中,想法是如果B Bool,则省略B.Value == B.Undefined字段的输出。

type Bool struct {
    // Current value
    Value bool
    // Value if undefined
    Undefined bool
}

func (b Bool) MarshalJSON() ([]byte, error) {
    if b.Value == b.Undefined {
        return []byte{}, nil
    } else if b.Value {
        return ([]byte)("true"), nil
    }
    return ([]byte)("false"), nil
}

func main() {
    var example = struct {
        N int  `json:"foo"`
        B Bool `json:"value,omitempty"`
    }
    example.B = Bool{true, true}
    output, err := json.Marshal(example)
    if err != nil {
        panic(err)
    }
    fmt.Println(string(output))
}

Playground link

根据文档:



我返回一个空 byte slice ,这将导致错误:

panic: json: error calling MarshalJSON for type main.Bool: unexpected end of JSON input

goroutine 1 [running]:
main.main()
    /tmp/sandbox933539113/prog.go:32 +0x160

如果我设置了example.B = Bool{false, true},那么它将打印结果,但是尽管从"false"返回了Bool.MarshalJSON,但该字段仍然没有被省略。我究竟做错了什么?类型满足Marshaler接口(interface)的值是否有效地忽略了omtempty标签条目?

最佳答案

 if b.Value == b.Undefined {
        return []byte{}, nil

产生无效的JSON:返回0个字节。您的MarshalJSON方法必须返回有效的JSON,这意味着它必须返回某些内容。

如果您的目标是完全忽略该字段,则在未设置该字段的情况下,请使用指针,不要对其进行设置:

func main() {
    var example = struct {
        N int   `json:"foo"`
        B *Bool `json:"value,omitempty"`
    }
    example.B = Bool{N: true, B: nil}
    output, err := json.Marshal(example)
    if err != nil {
        panic(err)
    }
    fmt.Println(string(output))
}

如果要在Bool的值为特定值时完全忽略该字段,则必须在包含的struct上定义MarshalJSON方法,以便在需要时可以正确忽略该字段。

关于json - 误解了如何使用MarshalJSON,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/61135810/

10-13 00:14