简体   繁体   English

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

[英]Unable to deserialize struct (“value of type is not assignable to type”)

I'm running into an issue when trying to deserialize a struct.尝试反序列化结构时遇到问题。

I've tried using JSON and YAML, rewriting the struct to use a slice instead of a map (thinking it was an issue with my use of a map), all to no avail.我尝试使用 JSON 和 YAML,重写结构以使用切片而不是 map(认为这是我使用地图的问题),一切都无济于事。

The struct below contains the issue, specifically the Deserialize function.下面的结构包含问题,特别是反序列化 function。 I've replaced irrelevant code with ... :我已经用...替换了不相关的代码:

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

My test serializes a Collection, then attempts to deserialize the raw data from the first collection, into the second.我的测试序列化一个集合,然后尝试将第一个集合中的原始数据反序列化到第二个集合中。 It will then compare the two collections, but the issue presents itself during the deserialization:然后它将比较两个 collections,但在反序列化过程中会出现问题:

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

This is the error I keep running into:这是我一直遇到的错误:

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

Edit: I forgot to include the definition of Object .编辑:我忘了包括Object的定义。 Object is a very basic interface: Object是一个很基础的接口:

type Object interface {
    Update()
    Draw()
    Serialize()
    Deserialize()
}

This will work when you serialize because during serialization each element of the Objects array are structs.这将在您序列化时起作用,因为在序列化期间Objects数组的每个元素都是结构。 It will not work when you deserialize, because during deserialization, Objects is an empty array of interfaces.反序列化时它不起作用,因为在反序列化期间, Objects是一个空的接口数组。 You cannot unmarshal to an interface, only to a struct, or value.您不能解组到接口,只能解组到结构或值。

To fix this, you have to figure out the type of each individual array element in Objects during deserialization, and then deserialized based on the struct.要解决这个问题,您必须在反序列化期间弄清楚Objects中每个单独数组元素的类型,然后根据结构进行反序列化。 There are multiple ways this can be done.有多种方法可以做到这一点。

One way to do is to use a fat interface , a temporary struct containing all possible items:一种方法是使用fat interface ,一个包含所有可能项的临时结构:

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
}

Error checking is omitted.错误检查被省略。

Same approach can be used with a map[string]interface{} instead of unmarshalObject , but that would require lots of type assertions.同样的方法可以用于map[string]interface{}而不是unmarshalObject ,但这需要大量的类型断言。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM