You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言特定格式JSON反序列化遇空值问题求助

解决Go中JSON数组反序列化为空的问题

你的问题核心在于JSON结构和Go类型不匹配,咱们一步步拆解清楚:

1. 先明确你的JSON结构

你要解析的是一个长度为2的数组:

["Msg",{"cmd":"ack","id":"B81DA375B6C4AA49D262","ack":2,"from":"18094158994@c.us","to":"18099897215@c.us","t":1555446115}]

第一个元素是字符串"Msg",第二个是包含cmd/id等字段的对象。

2. 你的代码为什么失败?

你定义的SEND结构体是一个JSON对象类型(对应键值对结构),但你试图用它去反序列化一个JSON数组。Go的json包无法把数组映射到对象,所以反序列化后所有字段都保持零值,自然输出为空。

3. 解决方案:匹配JSON数组的Go类型

这里有两种常用方式来处理这种数组结构:

方法一:用[]interface{}接收,再做类型断言

这种方式简单直接,适合快速解析:

package main

import (
	"encoding/json"
	"fmt"
)

type MSG struct {
	CMD  string `json:"cmd"`
	ID   string `json:"id"`
	ACK  int    `json:"ack"`
	FROM string `json:"from"`
	TO   string `json:"to"`
	T    int64  `json:"t"`
}

func main() {
	data := `["Msg",{"cmd":"ack","id":"B81DA375B6C4AA49D262","ack":2,"from":"18094158994@c.us","to":"18099897215@c.us","t":1555446115}]`

	// 定义数组类型接收整个JSON
	var response [2]interface{}
	err := json.Unmarshal([]byte(data), &response)
	if err != nil {
		fmt.Println("反序列化失败:", err)
		return
	}

	// 取出第一个元素(消息类型)
	msgType, ok := response[0].(string)
	if !ok {
		fmt.Println("消息类型格式错误")
		return
	}
	fmt.Println("消息类型:", msgType)

	// 取出第二个元素并转换为MSG结构体
	msgDataBytes, err := json.Marshal(response[1])
	if err != nil {
		fmt.Println("转换数据失败:", err)
		return
	}
	var msg MSG
	err = json.Unmarshal(msgDataBytes, &msg)
	if err != nil {
		fmt.Println("解析消息数据失败:", err)
		return
	}
	fmt.Println("消息详情:", msg)
}

方法二:自定义UnmarshalJSON接口(更优雅)

如果需要频繁解析这种结构,推荐自定义一个类型并实现json.Unmarshaler接口,让解析逻辑更清晰:

package main

import (
	"encoding/json"
	"fmt"
)

type MSG struct {
	CMD  string `json:"cmd"`
	ID   string `json:"id"`
	ACK  int    `json:"ack"`
	FROM string `json:"from"`
	TO   string `json:"to"`
	T    int64  `json:"t"`
}

// 定义匹配JSON数组的自定义类型
type MsgResponse struct {
	Type string // 对应数组第一个元素
	Data MSG    // 对应数组第二个元素
}

// 实现json.Unmarshaler接口,自定义反序列化逻辑
func (r *MsgResponse) UnmarshalJSON(data []byte) error {
	// 先把JSON解析成数组
	var arr [2]interface{}
	if err := json.Unmarshal(data, &arr); err != nil {
		return err
	}

	// 验证第一个元素是字符串
	var ok bool
	r.Type, ok = arr[0].(string)
	if !ok {
		return fmt.Errorf("数组第一个元素不是字符串")
	}

	// 把第二个元素反序列化为MSG结构体
	dataBytes, err := json.Marshal(arr[1])
	if err != nil {
		return err
	}
	return json.Unmarshal(dataBytes, &r.Data)
}

func main() {
	data := `["Msg",{"cmd":"ack","id":"B81DA375B6C4AA49D262","ack":2,"from":"18094158994@c.us","to":"18099897215@c.us","t":1555446115}]`

	var response MsgResponse
	err := json.Unmarshal([]byte(data), &response)
	if err != nil {
		fmt.Println("反序列化失败:", err)
		return
	}

	fmt.Println("消息类型:", response.Type)
	fmt.Println("消息详情:", response.Data)
	fmt.Println("ACK值:", response.Data.ACK)
}

运行结果

两种方法都会输出类似这样的内容:

消息类型: Msg
消息详情: {ack B81DA375B6C4AA49D262 2 18094158994@c.us 18099897215@c.us 1555446115}

内容的提问来源于stack exchange,提问作者Victor Medrano

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:21:29