无法反序列化结构(“类型的值不可分配给类型”)

我在尝试反序列化结构时遇到问题。


我尝试过使用 JSON 和 YAML,重写结构以使用切片而不是地图(认为这是我使用地图的问题),但都无济于事。


下面的结构包含问题,特别是反序列化函数。我已将不相关的代码替换为...:


type Collection struct {

    Objects []Object `yaml:"objects,omitempty"`

}


...


func (c *Collection) Serialize() ([]byte, error) {

    return yaml.Marshal(c)

}


func (c *Collection) Deserialize(raw []byte) error {

    return yaml.Unmarshal(raw, c)

}

我的测试序列化一个集合,然后尝试将第一个集合中的原始数据反序列化到第二个集合中。然后它将比较两个集合,但问题在反序列化期间出现:


func TestDeserialize(t *testing.T) {

    c := NewCollection()


    // NewRect creates a Rect (inherits from Object)

    c.AddObject(NewRect(10,10,NewPos(0,0))


    c2 := NewCollection()


    v raw, err := c.Serialize()

    if err != nil {

        t.Fatalf("collection 1 failed to serialize: %v", err)

    }


    // deserialize raw 1 into 2

    // this is the call that fails

    err = c2.Deserialize(raw)

    if err != nil {

        t.Fatalf("collection 2 failed to deserialize: %v", err)

    }

}

这是我不断遇到的错误:


panic: reflect.Set: value of type map[interface {}]interface {} is not assignable to type bw.Object [recovered]

    panic: reflect.Set: value of type map[interface {}]interface {} is not assignable to type bw.Object [recovered]

    panic: reflect.Set: value of type map[interface {}]interface {} is not assignable to type bw.Object

编辑:我忘记包含 的定义Object。Object是一个非常基本的界面:


type Object interface {

    Update()

    Draw()

    Serialize()

    Deserialize()

}


红糖糍粑
浏览 139回答 1
1回答

蝴蝶不菲

这在序列化时会起作用,因为在序列化期间Objects数组的每个元素都是结构。当你反序列化时它将不起作用,因为在反序列化期间,Objects是一个空的接口数组。您不能解组到接口,只能解组到结构或值。要解决此问题,您必须在反序列化期间找出每个数组元素的类型Objects,然后根据结构进行反序列化。有多种方法可以做到这一点。一种方法是使用fat 接口,这是一个包含所有可能项目的临时结构:type unmarshalObject struct {   Type string `yaml:"type"`   // All possible fields of all possible implementations}type unmarshalCollection struct {    Objects []unmarshalObject `yaml:"objects,omitempty"`}func (c *Collection) Deserialize(raw []byte) error {    var intermediate unmarshalCollection    yaml.Unmarshal(raw, &intermediate)    c.Objects=make([]Object,0)    for _,object:=range intermediate.Objects {        switch object.Type {          case "rect":             c.Objects=append(c.Objects,Rectangle{X1:object.X1,...})          case "...":           ...        }    }    return nil}错误检查被省略。可以使用相同的方法来map[string]interface{}代替unmarshalObject,但这需要大量的类型断言。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go