如何正确重写 UnmarshalJSON?

Max*_*s S 5 go

我正在尝试编写一个简单的自定义封送拆收器,但失败了。请注意,我有一个具有三个功能的界面。Happy和结构体都通过嵌入实现所有三个必需功能的结构体Sad来实现此接口。emotion

问题是当我调用指向or 的指针UnmarshalJSON时不会被调用,我不明白为什么。您可以在Go Playground中重现确切的代码库或直接查看下面。您会注意到 while被正确调用,但不是。json.Unmarshal()HappySadMarshalJSONUnmarshalJSON

type Emotion interface {
    String() string
    MarshalJSON() ([]byte, error)
    UnmarshalJSON(data []byte) error 
}

type emotion struct {
    status string
}

func (s emotion) String() string {
    return s.status
}

func (s emotion) MarshalJSON() ([]byte, error) {
        fmt.Println("MarshalJSON is overriden: I am called fine")
    x := struct {
        Status string
    }{
        Status: s.String(),
    }

    return json.Marshal(x)
}

func (s *emotion) UnmarshalJSON(data []byte) error {
        fmt.Println("MarshalJSON is overriden: I am never called")
    y := struct {
        Status string
    }{
        Status: "",
    }

    err := json.Unmarshal(data, &y)
    if err != nil {
        return err
    }

    s.status = y.Status
    return nil
}

type Happy struct {
    *emotion
}

// Job is not in any detention
type Sad struct {
    *emotion
}


func main() {
    x := Happy{&emotion{status: "happy"}}
    jsonX, _ := json.Marshal(x)
    var y Emotion
    err := json.Unmarshal(jsonX, &y)
    fmt.Printf("%v", err)
}
Run Code Online (Sandbox Code Playgroud)

col*_*tor 3

您无法解组为抽象接口类型。接口值只是指向类型的指针(关联类型方法) - 它后面没有存储 - 因为抽象类型无法知道它将来可能具有的任何具体值的确切大小。

使用具体的值类型(也实现该接口)将起作用:

y2 := emotion{}
err = json.Unmarshal(jsonX, &y2)
Run Code Online (Sandbox Code Playgroud)

游乐场: https: //play.golang.org/p/8aCEjLgfKVQ

MarshalJSON is overriden: I am called fine
EXPECTED ERROR, Can't unmarshal into a non-concrete value: json: cannot unmarshal object into Go value of type main.Emotion

MarshalJSON is overriden: I am (fixed) and now called
SHOULD NOT ERROR: <nil>
VALUE: happy
Run Code Online (Sandbox Code Playgroud)