在Go中解组JSON标记的联合

时间:2019-05-05 18:05:26

标签: json go unmarshalling

我正在尝试解组Google Actions的JSON请求。这些数组具有如下标记的联合:

function addTwo() {
  for (i = 0; i <= 100; i += 2) {
    console.log(i);
  }
}

addTwo();

很明显,我可以将其编组为{ "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf", "inputs": [{ "intent": "action.devices.QUERY", "payload": { "devices": [{ "id": "123", "customData": { "fooValue": 74, "barValue": true, "bazValue": "foo" } }, { "id": "456", "customData": { "fooValue": 12, "barValue": false, "bazValue": "bar" } }] } }] } { "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf", "inputs": [{ "intent": "action.devices.EXECUTE", "payload": { "commands": [{ "devices": [{ "id": "123", "customData": { "fooValue": 74, "barValue": true, "bazValue": "sheepdip" } }, { "id": "456", "customData": { "fooValue": 36, "barValue": false, "bazValue": "moarsheep" } }], "execution": [{ "command": "action.devices.commands.OnOff", "params": { "on": true } }] }] } }] } etc. 并使用完全动态类型强制转换和所有方法对其进行解码,但是Go对解码结构具有不错的支持。有没有办法在Go语言中优雅地做到这一点(例如like you can in Rust)?

我觉得您几乎可以通过阅读本章的编组信息来做到这一点:

interface{}

但是,一旦拥有type Request struct { RequestId string Inputs []struct { Intent string Payload interface{} } } ,似乎没有任何方法可以将其反序列化为Payload interface{}(除了对其进行序列化和再次反序列化很麻烦。有什么好的解决方案吗?

1 个答案:

答案 0 :(得分:2)

您可以将其Payload解组为interface{},而不必将其解组为json.RawMessage,然后根据Intent的值对其进行解组。这显示在json docs的示例中:

https://golang.org/pkg/encoding/json/#example_RawMessage_unmarshal

将该示例与您的JSON一起使用,并构造代码,如下所示:

type Request struct {
    RequestId string
    Inputs    []struct {
        Intent   string
        Payload  json.RawMessage
    }
}

var request Request
err := json.Unmarshal(j, &request)
if err != nil {
    log.Fatalln("error:", err)
}
for _, input := range request.Inputs {
    var payload interface{}
    switch input.Intent {
    case "action.devices.EXECUTE":
        payload = new(Execute)
    case "action.devices.QUERY":
        payload = new(Query)
    }
    err := json.Unmarshal(input.Payload, payload)
    if err != nil {
        log.Fatalln("error:", err)
    }
    // Do stuff with payload
}