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

Go语言如何解析数组元素为多类型无键的JSON响应并遍历条目?

问题解决方法

背后核心逻辑

Go标准库的encoding/json包解析JSON时,不需要强制要求键名映射:

  • 解析JSON对象时,会按struct标签的键名匹配赋值
  • 解析JSON数组时,会按元素顺序和目标变量的类型匹配赋值
    你之前遍历失败的原因是:将JSON解析到map[string]interface{}后,bots对应的值是interface{}通用类型,必须先做类型断言转为数组类型才能操作,这种写法类型不安全,更推荐用下面的结构体方案实现。

方案1:快速实现(直接用二维接口切片)

直接定义和JSON结构匹配的结构体,bots字段声明为二维空接口切片,解析后按索引取值+类型断言即可:

package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"time"
)

// 外层响应结构体,和JSON字段一一对应
type BotResponse struct {
	Total int             `json:"_total"`
	Bots  [][]interface{} `json:"bots"`
}

func main() {
	// 发起接口请求
	resp, err := http.Get("https://api.twitchinsights.net/v1/bots/online")
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	// 解析JSON响应
	var botResp BotResponse
	err = json.NewDecoder(resp.Body).Decode(&botResp)
	if err != nil {
		panic(err)
	}

	// 遍历所有bot条目
	for _, botItem := range botResp.Bots {
		// 按索引取值+类型校验
		botName, ok := botItem[0].(string)
		if !ok {
			continue
		}
		viewCountRaw, ok := botItem[1].(float64)
		if !ok {
			continue
		}
		timestampRaw, ok := botItem[2].(float64)
		if !ok {
			continue
		}
		onlineTime := time.Unix(int64(timestampRaw), 0)

		fmt.Printf("Bot名称:%s,在线观众:%d,上线时间:%s\n", 
			botName, int(viewCountRaw), onlineTime.Format("2006-01-02 15:04:05"))
	}
}

方案2:规范实现(自定义结构体实现反序列化接口)

如果需要类型安全、避免每次遍历做类型断言,可以让自定义的Bot结构体实现json.Unmarshaler接口,自动把数组元素映射到结构体字段:

package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"time"
)

// 自定义Bot结构体,字段含义明确
type Bot struct {
	Name       string
	ViewCount  int
	OnlineTime time.Time
}

// 实现json.Unmarshaler接口,自定义数组到结构体的映射逻辑
func (b *Bot) UnmarshalJSON(data []byte) error {
	var rawEntry []interface{}
	if err := json.Unmarshal(data, &rawEntry); err != nil {
		return err
	}
	if len(rawEntry) != 3 {
		return fmt.Errorf("非法的bot条目长度:%d", len(rawEntry))
	}

	// 逐个转换类型赋值
	var ok bool
	b.Name, ok = rawEntry[0].(string)
	if !ok {
		return fmt.Errorf("bot名称类型非法")
	}
	viewCountRaw, ok := rawEntry[1].(float64)
	if !ok {
		return fmt.Errorf("观众数类型非法")
	}
	b.ViewCount = int(viewCountRaw)
	timestampRaw, ok := rawEntry[2].(float64)
	if !ok {
		return fmt.Errorf("时间戳类型非法")
	}
	b.OnlineTime = time.Unix(int64(timestampRaw), 0)
	return nil
}

// 外层响应结构体直接用[]Bot作为bots字段类型
type BotResponse struct {
	Total int   `json:"_total"`
	Bots  []Bot `json:"bots"`
}

func main() {
	// 发起请求逻辑和方案1一致
	resp, err := http.Get("https://api.twitchinsights.net/v1/bots/online")
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	var botResp BotResponse
	err = json.NewDecoder(resp.Body).Decode(&botResp)
	if err != nil {
		panic(err)
	}

	// 遍历不需要再做类型断言,直接取结构体字段即可
	for _, bot := range botResp.Bots {
		fmt.Printf("Bot名称:%s,在线观众:%d,上线时间:%s\n",
			bot.Name, bot.ViewCount, bot.OnlineTime.Format("2006-01-02 15:04:05"))
	}
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 04:48:03