我有一个 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/