解析一个包含不同类型结构体的JSON数组

huangapple go评论109阅读模式
英文:

Unmarshal a JSON array of heterogeneous structs

问题

我想要反序列化一个包含某个接口Entity数组的对象:

type Result struct {
    Foo int;
    Bar []Entity;
};

Entity是由多个结构体类型实现的接口。JSON数据通过每个实体中的"type"字段来标识结构体类型。例如:

{"type":"t1","field1":1}
{"type":"t2","field2":2,"field3":3}

我应该如何反序列化Result类型,以正确填充数组?从我所看到的,我需要:

  1. Result上实现UnmarshalJSON
  2. Bar解析为[]*json.RawMessage
  3. 将每个原始消息解析为map[string]interface{}
  4. 检查原始消息中的"type"字段。
  5. 创建适当类型的结构体。
  6. 再次解析原始消息,这次解析到刚创建的结构体中。

这听起来非常繁琐和无聊。有没有更好的方法来做这个?或者我是在反过来做,有没有更规范的方法来处理异构对象数组?

英文:

I want to deserialise an object that includes an array of a some interface Entity:

type Result struct {
    Foo int;
    Bar []Entity;
};

Entity is an interface that is implemented by a number of struct types. JSON data identifies the struct type with a "type" field in each entity. E.g.

{"type":"t1","field1":1}
{"type":"t2","field2":2,"field3":3}

How would I go about deserialising the Result type in such a way that it correctly populates the array. From what I can see, I have to:

  1. Implement UnmarshalJSON on Result.
  2. Parse Bar as a []*json.RawMessage.
  3. Parse each raw message as map[string]interface{}.
  4. Check "type" field in the raw message.
  5. Create a struct of appropriate type.
  6. Parse the raw message again, this time into the just created struct.

This all sounds very tedious and boring. Is there a better way to do this? Or am I doing it backwards, and there is a more canonical method to handle an array of heterogeneous objects?

答案1

得分: 5

我认为你的过程可能比必要的要复杂一些,可以参考http://play.golang.org/p/0gahcMpuQc。一个单独的map[string]interface{}可以处理很多事情。

或者,你可以创建一个类型,如下所示:

struct EntityUnion {
    Type string
    // 来自t1的字段
    // 来自t2的字段
    // ...
}

将其解组为该类型;它将设置Type字符串并填充所有可以从JSON数据中获取的字段。然后,你只需要一个小函数将字段复制到特定的类型中。

英文:

I think your process is probably a bit more complicated than it has to be, see http://play.golang.org/p/0gahcMpuQc. A single map[string]interface{} will handle a lot of that for you.

Alternatively, you could make a type like

struct EntityUnion {
    Type string
    // Fields from t1
    // Fields from t2
    // ...
}

Unmarshal into that; it will set the Type string and fill in all the fields it can get from the JSON data. Then you just need a small function to copy the fields to the specific type.

huangapple
  • 本文由 发表于 2013年4月14日 16:07:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/15996997.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定