为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
红糖糍粑 2023-07-31 16:35:19
我在尝试反序列化结构时遇到问题。我尝试过使用 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()}
查看完整描述

1 回答

?
蝴蝶不菲

TA贡献1810条经验 获得超4个赞

这在序列化时会起作用,因为在序列化期间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,但这需要大量的类型断言。


查看完整回答
反对 回复 2023-07-31
  • 1 回答
  • 0 关注
  • 138 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信