尝试反序列化结构时遇到问题。
我尝试使用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)
}
我的测试对一个Collection进行序列化,然后尝试将第一个Collection中的原始数据反序列化到第二个Collection中。然后它将比较这两个集合,但是在反序列化过程中会出现问题:
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()
}
答案 0 :(得分:0)
这在您进行序列化时将起作用,因为在序列化期间,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
,但这将需要大量类型断言。