我试图写一个简单的自定义封送拆收器,但失败了。注意,我有一个具有三个功能的接口。 HappySad结构都通过嵌入实现所有三个必需功能的emotion结构来实现此接口。

问题是,当我在指向UnmarshalJSONjson.Unmarshal()的指针上调用Happy时,无法调用Sad,但我不明白为什么。您可以在Go Playground中重现确切的代码库,或者只看下面。您会注意到,虽然正确调用了MarshalJSON,但未正确调用UnmarshalJSON

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)
}

最佳答案

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

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

y2 := emotion{}
err = json.Unmarshal(jsonX, &y2)

游乐场: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

关于go - 如何正确覆盖UnmarshalJSON?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56469322/

10-11 07:16