当嵌入类型具有 UnmarshalJSON 时,json.Unmarshal 失败

我正在尝试解组具有嵌入类型的结构。当嵌入类型具有 UnmarshalJSON 方法时,外部类型的解组失败:


https://play.golang.org/p/Y_Tt5O8A1Q


package main



import (

    "fmt"


    "encoding/json"

)


type Foo struct {

    EmbeddedStruct

    Field string

}


func (d *Foo) UnmarshalJSON(from []byte) error {

    fmt.Printf("Foo.UnmarshalJSON\n")


    type Alias Foo

    alias := &Alias{}

    if err := json.Unmarshal(from, alias); err != nil {

        return fmt.Errorf("Error in Foo.UnmarshalJSON: json.Unmarshal returned an error:\n%v\n", err)

    }

    *d = Foo(*alias)


    return nil

}


type EmbeddedStruct struct {

    EmbeddedField string

}


func (d *EmbeddedStruct) UnmarshalJSON(from []byte) error {

    fmt.Printf("EmbeddedStruct.UnmarshalJSON\n")


    type Alias EmbeddedStruct

    alias := &Alias{}

    if err := json.Unmarshal(from, alias); err != nil {

        return fmt.Errorf("Error in EmbeddedStruct.UnmarshalJSON: json.Unmarshal returned an error:\n%v\n", err)

    }

    *d = EmbeddedStruct(*alias)


    return nil

}


func main() {


    data := `{"EmbeddedField":"embeddedValue", "Field": "value"}`

    foo := &Foo{}


    json.Unmarshal([]byte(data), foo)


    fmt.Printf("Foo: %v\n", foo)


    if foo.EmbeddedField != "embeddedValue" {

        fmt.Printf("Unmarshal didn't work, EmbeddedField value is %v. Should be 'embeddedValue'\n", foo.EmbeddedField)

    }


    if foo.Field != "value" {

        fmt.Printf("Unmarshal didn't work, Field value is %v. Should be 'value'\n", foo.Field)

    }


}

输出是:


Foo.UnmarshalJSON

EmbeddedStruct.UnmarshalJSON

Foo: &{{embeddedValue} }

Unmarshal didn't work, Field value is . Should be 'value'

...所以这两个自定义解组函数都运行了。嵌入结构中的值是正确的,但外部结构中的值丢失了。


如果我们简单地删除 EmbeddedStruct.UnmarshalJSON 方法,它会按预期工作。


难道我做错了什么?这是预期的吗?还是bug?我确信有一种方法可以调整我的 UnmarshalJSON 方法以使其正常工作。


千巷猫影
浏览 318回答 1
1回答

慕侠2389804

这是预期的。创建别名时:type Alias FooAlias不会继承 的方法,Foo因为它是具有不同方法集的不同类型,这是您想要避免无限递归的目标。然而,内嵌EmbeddedStruct的UnmarshalJSON方法反而会得到提升!因此,Alias将有一个UnmarshalJSON方法只解组EmbeddedStruct的值,而不是使用您想要的默认解组。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go