我有一个web套接字连接,它在JSON对象中发送不同类型的消息,我想将内容解组到一些已知的结构中。为此,我想我应该做以下几点:
步骤1)将JSON解组到通用映射[字符串]接口{}
第2步)找到我要找的钥匙
步骤3)尝试将值强制转换为我的类型之一(此操作失败)
步骤3(可选)json封送此值并将其解组到我的已知结构
如果我尝试使用myStruct,ok:=value。(myType)它将失败,但如果我使用json。封送(值),然后是json。对我的结构来说,它工作得很好。我应该这样做吗?去json-
示例代码:
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)
}
}
}
另一种解决方案是在所有消息(例如:type
)之间使用一个公共键,该键指示消息的类型。在此之后,如果消息不够复杂,则可以从其他映射键/类型断言映射值构建原始结构:
从我编写的一些相关websocket代码中可以看出:https://github.com/blaskovicz/cut-me-some-slack/blob/master/chat/message.go#L66
func DecodeClientMessage(c *ClientMessage) (typedMessage interface{}, err error) {
buff := map[string]string{}
err = json.NewDecoder(bytes.NewReader(c.Raw)).Decode(&buff)
if err != nil {
return
}
switch t := buff["type"]; t {
case "message":
channelID := buff["channel_id"]
if channelID == "" {
err = fmt.Errorf("invalid client message received: missing channel_id")
return
}
cms := &ClientMessageSend{ChannelID: channelID, Text: buff["text"]}
if cms.Text == "" {
err = fmt.Errorf("invalid client message received: missing text")
} else {
typedMessage = cms
}
... 然后调用方代码执行结果。(类型)
断言和切换:https://github.com/blaskovicz/cut-me-some-slack/blob/master/chat/hub.go#L150
switch m := raw.(type) {
case *ClientMessageHistory:
channelID := h.resolveSlackChannel(m.ChannelID)
if channelID == "" {
log.Printf("error: no channel found matching %s\n", m.ChannelID)
return
}
var username string
if c.Client.User != nil {
username = c.Client.User.Username
} else {
username = "<anonymous>"
}
log.Printf("sending previous messages for channel %s to client %s\n", channelID, username)
for _, prevMessage := range h.previousMessages(channelID, m.Limit) {
c.Client.send <- prevMessage
}
您需要创建一个包含所有可能接收到的密钥的结构,然后解组一次,最后根据哪些密钥是nil
您可以决定得到的是什么类型的数据包。
下面的示例显示此行为:https://play.golang.org/p/aFG6M0SPJs
package main
import (
"encoding/json"
"fmt"
"strings"
)
type Ack struct {
Messages []string `json:"messages"`
}
type Packet struct {
Ack * Ack `json:"ack"`
Ping * string `json:"ping"`
}
func runTest(testJSON []byte) {
var p = Packet{}
err := json.Unmarshal(testJSON, &p)
if err != nil {
fmt.Println("error unmarshalling: ", err)
}
if (p.Ack != nil) {
fmt.Println("Got ACK: ", strings.Join(p.Ack.Messages, ", "));
} else if (p.Ping != nil){
fmt.Println("Got PING");
}
}
func main() {
tests := [][]byte{
[]byte(`{"ack":{"messages":["Hi there","Hi again"]}}`),
[]byte(`{"ping": "Are you there?"}`),
}
for _, test := range tests {
runTest(test)
}
}
一种解决方案是通过将值解组为json来部分解组数据。RawMessage
而不是接口{}
var myMap map[string]json.RawMessage
在稍后的开关中,这仍然是必需的,不需要列表。只要做:
err = json.Unmarshal(v, &myAck)
游乐场:https://play.golang.org/p/NHd3uH5e7z
问题内容: 输出: 我有api调用返回的结果,它就像对象数组(json数组)的复杂格式。我需要通过golang解析该结果,我该如何实现?以下数据是我的结果,它是从api调用获取的。 问题答案: 您仅错过了一点:您需要导出结构的字段: 它将起作用(在Go Playground上尝试): 请注意,JSON文本包含带有小写字母文本的字段名称,但是包足够“聪明”以匹配它们。如果它们完全不同,则可以使用st
问题内容: 如何在Android中解析如下数组? 如您所见,没有像其他示例数组那样定义数组的键,例如: 对于第二个数组,我可以轻松地使用并使用: 但是,很明显,第一个数组没有键。那么,如何处理呢?标准的Android库甚至可能吗? 问题答案: 您是否尝试过这样做?
问题内容: 我似乎找不到使用Dart语言在没有密钥的情况下解析json数组的解决方案。我所能找到的就是使用Java。我需要解析这样的内容。 Java解决方案来自这里 如果我有重复的问题,请告知我。谢谢! 问题答案: 只需json.decode正常使用,例如: 碰巧的成员l都将int小号
问题内容: 我正在使用一个API,该API返回如下所示的JSON 在Swift中,我使用两个函数来获取并解析JSON 然后我用 可以很好地解析JSON。当我打印出 我得到了数组的所有内容。但是,我无法访问每个单独的索引。我很肯定这是一个数组,因为我之间 返回正确的长度。但是,如果我尝试通过使用访问单个索引 XCode关闭语法高亮显示并给我以下信息: 并且代码将无法编译。 这是XCode 6的错误,
问题内容: 在python中,您可以获取json对象并从中获取特定项目,而无需声明结构,将其保存到结构中,然后像Go中那样获取值。有没有一种包装或更简单的方法来存储Go中来自json的特定值? 蟒蛇 走 问题答案: 您可以解码为,然后按键获取元素。 通常首选结构,因为它们对类型更明确。您只需要在所需的JSON中声明字段,而无需像使用映射(隐式编码/ json处理)那样键入assert值。
问题内容: 我在s3中有很多gzip日志文件,其中有3种类型的日志行:b,c,i。我和c都是单层json: 类型b是深度嵌套的json。我碰到这个要点,谈论要编译一个罐子来完成这项工作。由于我的Java技能还不算出色,因此我真的不知道该怎么做。 由于类型i和c并不总是相同的顺序,因此很难在生成正则表达式中指定所有内容。Pig是否可以处理JSON(在gzip文件中)?我正在使用在Amazon Ela