Go语言JSON解析与生成:结构体、Map转换及自定义标签详解

何川
何川
发布时间:2026-10-15 | 5人浏览过
原创

掌握Go语言的JSON处理是后端开发的基础技能。本文不仅梳理了JSON的数据格式规范,更通过代码实例演示了使用 encoding/json 包将JSON解析为结构体(Struct)和动态Map的技巧。此外,详细讲解了如何通过在 Struct 字段上使用 json tag(如 omitempty)来自定义序列化行为,确保生成的 JSON 符合接口标准。

JSON基础语法与数据结构

Go语言的 encoding/json 包严格遵循 RFC 7159 标准,其语法也是 JavaScript 语法的子集。在处理 JSON 前,需了解其基本构成规则,这有助于理解后续解析逻辑中的类型映射。

  • 数据格式:所有数据由键值对组成,以逗号分隔。
  • 容器标识:大括号 {} 保存对象,中括号 [] 保存数组。
  • 数据类型:
  1. 字符串:必须使用双引号包裹,例如 "name": "runoob"。
  2. 数字:支持整数和浮点数,无需引号,例如 "age":30。
  3. 布尔值:小写的 true 或 false。
  4. null值:表示空值,写作 null。

示例:常见JSON结构

{
  "name": "server_01",
  "ip": "127.0.0.1",
  "status": true,
  "sites": [
    {
      "name": "site_a",
      "url": "www.example.com"
    }
  ]
}

第一步:将JSON解析为结构体 (Unmarshal to Struct)

当JSON结构固定且已知时,解析为 Go 结构体是最安全的方式。这要求目标结构体的字段名必须与 JSON Key 匹配(或通过 Tag 映射),且字段必须是导出字段(首字母大写)。

1. 定义结构体并执行解析

我们需要定义对应的结构体,并使用 json.Unmarshal 将字节流转换为结构体实例。注意检查返回的 err,若Key不匹配或类型错误会报错。

package main

import (
	"encoding/json"
	"fmt"
)

// 定义结构体字段首字母大写,否则json包无法访问
type Server struct {
	ServerName string `json:"serverName"`
	ServerIP   string `json:"serverIP"`
}

type Serverslice struct {
	Servers []Server `json:"servers"`
}

func main() {
	// JSON 原始数据
	str := `{"servers":[{"serverName":"Guangzhou_Base","serverIP":"127.0.0.1"},{"serverName":"Beijing_Base","serverIP":"127.0.0.2"}]}`

	var s Serverslice
	// 核心动作:将 JSON 字节切片解析到 s 的地址引用中
	err := json.Unmarshal([]byte(str), &s)
	if err != nil {
		fmt.Println("解析错误:", err)
		return
	}

	// 验证结果
	fmt.Printf("解析后的结构体: %#v\n", s)
	fmt.Printf("第一个服务器名称: %s\n", s.Servers[0].ServerName)
}

第二步:将JSON动态解析为 Map

当JSON键值不固定,或者只需提取部分字段时,使用 map[string]interface{} 更为灵活。对于已知全为字符串结构的场景,也可直接映射为 map[string]string。

1. 解析为 map[string]string

此方式适合简单配置项解析,直接丢弃非字符串类型的字段。

package main

import (
	"encoding/json"
	"fmt"
)

func main() {
	b := []byte(`{"IP": "127.0.0.1", "name": "SKY", "count": 10}`)

	m := make(map[string]string)
	// Unmarshal 遇到数字类型 key 值为 10 时会跳过或报错取决于版本/实现,通常建议用 interface{}
	err := json.Unmarshal(b, &m)
	
	// 注意:如果JSON包含非字符串值(如数字),map[string]string 可能捕获不到该Key
	if err != nil {
		fmt.Println("Umarshal failed:", err)
		return
	}

	fmt.Println("Map内容:", m)
	for k, v := range m {
		fmt.Printf("Key: %s, Value: %s\n", k, v)
	}
}

提示:若JSON中包含数字、布尔或嵌套对象,通用做法是使用 m := make(map[string]interface{}) 进行接收,后续再进行类型断言。

第三步:将结构体序列化为JSON (Marshal)

在使用 json.Marshal 将Go对象转换为JSON字符串时,可以通过设置 Struct Tag 来控制输出格式。这是对接 API 或存储数据的关键步骤。

1. 常用 Tag 参数说明

  • json:"fieldName":指定输出的 JSON Key 名称。
  • json:"-":在序列化时忽略该字段。
  • json:"fieldName,omitempty":如果字段值为零值(如空串、0、nil),则在输出 JSON 中省略该 Key。
  • json:"fieldName,string":强制将该字段序列化为 JSON 中的字符串形式(常用于 ID 或 Bigint)。

2. 执行序列化

以下代码展示了如何在生成 JSON 时应用这些策略,自动处理空值并定制字段名。

package main

import (
	"encoding/json"
	"fmt"
)

type Server struct {
	// 使用 omitempty,若 ServerIP 为空则不会出现在最终 JSON 中
	ServerName string `json:"serverName,omitempty"`
	ServerIP   string `json:"serverIP,omitempty"`
}

type Serverslice struct {
	// 顶层数组包装
	Servers []Server `json:"servers"`
}

func main() {
	var s Serverslice
	s.Servers = append(s.Servers, Server{ServerName: "Guangzhou_Base", ServerIP: "127.0.0.1"})
	s.Servers = append(s.Servers, Server{}) // 第二个元素字段为空

	// Marshal 动作
	b, err := json.Marshal(s)
	if err != nil {
		fmt.Println("JSON 生成错误:", err)
		return
	}
	// 输出格式化 JSON 字符串
	fmt.Println(string(b))
}

输出示例:
上面的代码会将空字段跳过,仅输出带有值的服务器信息。这种机制能有效减小 JSON 体积,避免前端接收无意义字段。

总结与注意事项

Go语言处理JSON的核心在于 encoding/json 包的 Marshal(转JSON)和 Unmarshal(解析JSON)。在实际工程中:

  1. 安全性:始终检查 Unmarshal 的错误返回值,防止因畸形JSON导致程序崩溃。
  2. 性能:对于超大数据量,推荐使用 json.Decoder 进行流式解析;一般业务场景直接使用 json.Unmarshal/Marshal 即可。
  3. 兼容性:利用 json:"field_name,omitempty" 优雅地处理可选字段,保持协议整洁。

以上就是Go语言解析JSON以及生成JSON的详细内容,更多关于Golang JSON编码解码的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表