简体   繁体   English

如何解组不同类型的 stream

[英]How to Unmarshal stream of different types

I have a stream of objects of different but known, types and I'm struggling to figure out how to unmarshal the JSON encoded stream into Go structs. I have a stream of objects of different but known, types and I'm struggling to figure out how to unmarshal the JSON encoded stream into Go structs.

Here is a sample slice for illustration purpose这是用于说明目的的示例切片

[
    {
        "uid": "xyz1",
        "type": "person",
        "name": "John",
        "surname": "King"
    },
    {
        "uid": "xyz2",
        "type": "thing",
        "car": "benz",
        "shoes": "nike"
    },
    {
        "uid": "xyz3",
        "type": "person",
        "name": "Mary",
        "surname": "Queen"
    }
]

As you can see there is a type field that informs the receiver about what is the type of the object.如您所见,有一个type字段通知接收器 object 的类型是什么。

Data maps into the following Go types in the stream which "share" UID and Type fields:数据映射到“共享” UIDType字段的 stream 中的以下 Go 类型:

type Person struct {
    UID     string
    Type    string
    Name    string
    Surname string
}

type Thing struct {
    UID   string
    Type  string
    Car   string
    Shoes string
}

I found a similar question here , though unanswered, it's a bit different from what I need to deal with.我在这里发现了一个类似的问题,虽然没有得到解答,但与我需要处理的问题有点不同。 Instead of being guaranteed a transaction keyspace as I've no guarantee what the payload should look like besides the type and uid fields.除了typeuid字段之外,我无法保证有效负载应该是什么样子,而不是保证transaction密钥空间。

Is there some way to this other than drowning deeply in reflect package?除了沉浸在reflect package 之外,还有其他方法吗?

Unmarshal to a slice of raw messages :原始消息解组:

var elems []json.RawMessage
err := json.Unmarshal(data, &elems)
if err != nil {
    log.Fatal(err)
}

For each element in the slice, unmarshal once to find the type and a second time to the specific type:对于切片中的每个元素,解组一次以查找类型,第二次解组为特定类型:

for _, elem := range elems {

    // Pick out the type field.

    var t struct {
        Type string
    }
    err := json.Unmarshal(elem, &t)
    if err != nil {
        log.Fatal(err)
    }

    // Decode to specific type based on value of the type field.

    switch t.Type {
    case "person":
        var p Person
        err := json.Unmarshal(elem, &p)
        if err != nil {
            log.Fatal(err)
        }
        fmt.Printf("%#v\n", p)
    case "thing":
        var t Thing
        err := json.Unmarshal(elem, &t)
        if err != nil {
            log.Fatal(err)
        }
        fmt.Printf("%#v\n", t)
    default:
        fmt.Printf("unknown type %s\n", t.Type)
    }

}

Run it on the Go playground .在 Go 操场上运行它

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

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