json - 如何在不解码两次的情况下在 golang 中解析 JSON

标签 json go

我有一个 Web 套接字连接,它在 JSON 对象中发送不同类型的消息,我想将内容解码为一些已知的结构。 为此,我认为我应该执行以下操作:

第 1 步)将 JSON 解码为通用映射[字符串]接口(interface){}

第 2 步)找到我要找的 key

第 3 步)尝试将值转换为我的类型之一(失败)

第 3 步备用)json 编码此值并将其解编为我已知的结构

如果我尝试使用 myStruct, ok := value.(myType) 它会失败,但是如果我对 myStruct 使用 json.marshal(value) 然后 json.unmarshal,它就可以正常工作.那是我应该做的吗?去 json-> map[string]interface{} -> json -> myStruct 对我来说似乎是多余的。

示例代码:

https://play.golang.org/p/to_0Id_ja9

package main

import (
    "encoding/json"
    "fmt"
)

type Ping struct {
    Ping string `json:"ping"`
}

type Ack struct {
    Messages []Message `json:"messages"`
}

type Message string

func main() {
    testJSON := []byte(`{"ack":{"messages":["Hi there","Hi again"]}}`)
    var myAck = Ack{}
    var myMap map[string]interface{}
    err := json.Unmarshal(testJSON, &myMap)
    if err != nil {
        fmt.Println("error unmarshalling: ", err)
    }
    for k, v := range myMap {
        fmt.Printf("key: %s, value: %s \n", k, v)

        switch k {
        case "ping":
            fmt.Println(k, " is a ping", v)
        case "ack":
            fmt.Println(k, " is an ack containing a message list")
            ackjson, err := json.Marshal(v)
            if err != nil {
                fmt.Println("marshal error: ", err)
            }
            err = json.Unmarshal(ackjson, &myAck)
            if err != nil {
                fmt.Println("unmarshal error", err)
            } else {
                fmt.Println("New ack object: ", myAck)
            }
        default:
            fmt.Printf("%s is of a type (%T) I don't know how to handle", k, v)
        }
    }
}

最佳答案

一种解决方案是通过将值解码为 json.RawMessage 来部分解码数据。而不是接口(interface){}

var myMap map[string]json.RawMessage

稍后在仍然需要的切换中,您不需要编码。只是做:

err = json.Unmarshal(v, &myAck)

Playground : https://play.golang.org/p/NHd3uH5e7z

关于json - 如何在不解码两次的情况下在 golang 中解析 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46536234/

相关文章:

sorting - 去 sort.IntSlice() 实现

go - 从 SSH session Golang 读取数据

ios - 在 Swift 中解析和存储 JSON

python - 将 SqlAlchemy orm 结果转换为 dict

json - 如何在javascript中以异步方式解析和Stringify

go - Json 解码为结构,根据路径使用不同的请求类型

java - 如何在Android中使用JAVA将JSON保存在字符串变量中?

json - 将 bash 变量传递给 jq

concurrency - 并发 Go 例程的相互执行问题

Golang net/http/transport proxy CONNECT方法头支持