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

Go语言解析非结构化JSON并提取目标列表的解决方案

在Go中解析非结构化JSON并提取目标列表的方案

你的问题核心是这个JSON顶层是混合类型的数组(包含数组、字符串、null),直接json.Unmarshal到单一struct或map会失败,因为类型不匹配。可以通过以下步骤解决:

步骤1:定义目标数据的结构体

先把你要提取的列表元素对应的结构体定义好,字段名和JSON键一一对应:

type User struct {
	UserID   string `json:"user_id"`
	Username string `json:"username"`
}

type Item struct {
	ID           string `json:"id"`
	Text         string `json:"text"`
	User         User   `json:"user"`
	CreatedAtUTC string `json:"created_at_utc"`
	Status       string `json:"status"`
}

步骤2:解析顶层混合数组,提取目标元素

先将整个响应Unmarshal到[]interface{}类型(适配顶层数组的混合元素类型),然后提取第一个元素,再将其转换为目标结构体切片:

package main

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

type User struct {
	UserID   string `json:"user_id"`
	Username string `json:"username"`
}

type Item struct {
	ID           string `json:"id"`
	Text         string `json:"text"`
	User         User   `json:"user"`
	CreatedAtUTC string `json:"created_at_utc"`
	Status       string `json:"status"`
}

func main() {
	res, err := http.Get("url_of_server")
	if err != nil {
		fmt.Printf("请求失败: %v\n", err)
		return
	}
	defer res.Body.Close()

	body, err := io.ReadAll(res.Body)
	if err != nil {
		fmt.Printf("读取响应失败: %v\n", err)
		return
	}

	// 先Unmarshal到混合类型数组,适配顶层的多样元素
	var raw []interface{}
	if err := json.Unmarshal(body, &raw); err != nil {
		fmt.Printf("解析JSON失败: %v\n", err)
		return
	}

	// 提取第一个元素,断言为数组类型(即你要的目标列表)
	rawItems, ok := raw[0].([]interface{})
	if !ok {
		fmt.Println("第一个元素不是数组类型")
		return
	}

	// 方式1:重新序列化+反序列化,简洁易维护
	itemsJSON, err := json.Marshal(rawItems)
	if err != nil {
		fmt.Printf("序列化失败: %v\n", err)
		return
	}

	var items []Item
	if err := json.Unmarshal(itemsJSON, &items); err != nil {
		fmt.Printf("解析目标列表失败: %v\n", err)
		return
	}
	fmt.Printf("提取到的列表:\n%+v\n", items)

	// 方式2:直接遍历断言,避免二次序列化开销
	var itemsDirect []Item
	for _, rawItem := range rawItems {
		itemMap, ok := rawItem.(map[string]interface{})
		if !ok {
			continue
		}
		userMap := itemMap["user"].(map[string]interface{})
		item := Item{
			ID:           itemMap["id"].(string),
			Text:         itemMap["text"].(string),
			User: User{
				UserID:   userMap["user_id"].(string),
				Username: userMap["username"].(string),
			},
			CreatedAtUTC: itemMap["created_at_utc"].(string),
			Status:       itemMap["status"].(string),
		}
		itemsDirect = append(itemsDirect, item)
	}
	fmt.Printf("直接转换的列表:\n%+v\n", itemsDirect)
}

关键说明

  • 直接用struct/map失败的原因:顶层JSON是混合类型数组,元素分别是数组、字符串、null,无法匹配单一的struct或map类型。
  • 用[]interface{}接收整个数组后,通过类型断言提取第一个元素,再转换为目标结构体切片即可。
  • 两种转换方式各有优劣:重新序列化方式代码简洁、不易出错;直接断言方式避免了二次序列化的性能开销,适合数据量较大的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 19:30:53