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

如何在Go语言中获取JSON响应中的key3数据?

问题描述

我发起了一个JSON请求,代码如下:

req, err := http.NewRequest("GET", myPath, nil)
if err != nil {
  panic(err)
}

resp, err := http.DefaultClient.Do(req)
if err != nil {
  panic(err)
}

defer resp.Body.Close()
var j map[string]interface{}
err = json.NewDecoder(resp.Body).Decode(&j)
if err != nil {
  panic(err)
}

此时返回的是map[string]interface{}类型的数据,但JSON的实际结构为:

{
  "key1": "string",
  "key2": "string",
  "key3": [
   { "key1": "string", "key2": 123, "key3": ["str1", "str2"] },
   { "key1": "string", "key2": 456, "key3": ["str3", "str4"] },
   ...更多元素
  ] 
}

我想获取其中的key3数据,尝试遍历map时遇到瓶颈:

for key, value := range j {
  if key == "key3" {
    // 不知道怎么继续处理
  }
}

我也曾尝试将JSON响应反序列化为结构体,但出现错误:

type key3Struct struct {
  key1 string
  key2 string
  key3 []string
}

type ResponseStruct struct {
  key1 string
  key2 string 
  key3 []key3Struct
}

// 尝试1
j = ResponseStruct{}
json.NewDecoder(resp.Body).Decode(&j)
==> 错误:无法将map[string]interface{}转换为ResponseStruct{}

// 尝试2
json.Unmarshal(resp.Body, &j)
==> 结果是[ {} ],没有数据

请问如何正确获取JSON响应中的key3数据?


解决方案

方法一:直接解析map[string]interface{}

如果坚持使用map[string]interface{},需要通过类型断言将interface{}转换为具体类型,步骤如下:

for key, value := range j {
  if key == "key3" {
    // 先断言为[]interface{}(JSON数组对应Go的[]interface{})
    key3Items, ok := value.([]interface{})
    if !ok {
      panic("key3不是数组类型")
    }

    // 遍历数组中的每个元素
    for _, item := range key3Items {
      // 将元素断言为map[string]interface{}(JSON对象对应Go的map)
      itemMap, ok := item.(map[string]interface{})
      if !ok {
        panic("key3中的元素不是对象类型")
      }

      // 提取各个字段,注意类型匹配:
      // JSON字符串对应string,JSON数字默认解析为float64(需要转成int),JSON数组对应[]interface{}
      key1 := itemMap["key1"].(string)
      key2 := int(itemMap["key2"].(float64)) // 转换为int
      key3Raw := itemMap["key3"].([]interface{})
      
      // 将[]interface{}转为[]string
      key3 := make([]string, len(key3Raw))
      for i, s := range key3Raw {
        key3[i] = s.(string)
      }

      // 这里可以使用提取出的key1、key2、key3
      fmt.Println(key1, key2, key3)
    }
  }
}

方法二:使用结构体反序列化(推荐)

这种方法更简洁、类型安全,你之前的错误主要有三个:

  1. 结构体字段首字母小写,无法被encoding/json包访问(Go仅导出首字母大写的字段)
  2. 字段类型不匹配(JSON中key2是int,你定义为string)
  3. 重复读取resp.Body(第一次Decode后,Body的游标已经到末尾,第二次读取无数据)

修正后的结构体

// 定义key3数组中的元素结构体
type Key3Item struct {
    Key1 string   `json:"key1"` // json标签指定JSON中的键名
    Key2 int      `json:"key2"` // 匹配JSON中的int类型
    Key3 []string `json:"key3"`
}

// 定义整个响应的结构体
type Response struct {
    Key1 string     `json:"key1"`
    Key2 string     `json:"key2"`
    Key3 []Key3Item `json:"key3"`
}

正确的反序列化代码

req, err := http.NewRequest("GET", myPath, nil)
if err != nil {
  panic(err)
}

resp, err := http.DefaultClient.Do(req)
if err != nil {
  panic(err)
}
defer resp.Body.Close()

// 声明结构体变量,不要复用之前的map类型变量j
var respData Response
err = json.NewDecoder(resp.Body).Decode(&respData)
if err != nil {
  panic(err)
}

// 直接通过respData.Key3获取数据
for _, item := range respData.Key3 {
    fmt.Println(item.Key1, item.Key2, item.Key3)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 06:55:37