
本文详解 Go 中因 Base64 解码不完整或忽略 JSON 解析错误导致结构体数组字段为空的问题,通过修复解码逻辑、校验 JSON 完整性及正确处理错误,确保 []string 等嵌套字段被准确反序列化。
本文详解 go 中因 base64 解码不完整或忽略 json 解析错误导致结构体数组字段为空的问题,通过修复解码逻辑、校验 json 完整性及正确处理错误,确保 `[]string` 等嵌套字段被准确反序列化。
在 Go 中解析 JSON 时,看似简单的结构体绑定失败(如 Scp []string 始终为空),往往并非结构体标签(struct tag)写错,而是底层数据本身存在问题——最常见的是 Base64 解码后得到的字节流并非合法、完整的 JSON。
回顾问题代码:你将一个 Base64 字符串(encoded)解码为 []byte 后直接传给 json.Unmarshal,但未检查解码结果是否构成有效 JSON。实际上,该 Base64 字符串代表的 JWT Payload 是 URL-safe Base64 编码(RFC 7515),它默认省略了末尾的 = 填充符,且使用 - 和 _ 替代标准 Base64 中的 + 和 /。而 base64.StdEncoding 无法正确解码此类字符串,会导致解码后字节损坏(例如缺失结尾 }),致使 json.Unmarshal 静默失败(返回 nil 错误仅当输入为空或完全非法;部分截断 JSON 可能返回 io.ErrUnexpectedEOF 或 json.SyntaxError)。
✅ 正确做法是:
-
使用
base64.URLEncoding替代base64.StdEncoding(专为 JWT 设计); -
始终检查
json.Unmarshal的返回错误,绝不忽略; - (可选)解码后先打印原始 JSON 字符串,人工验证完整性。
以下是修正后的完整示例:
package main
import (
"encoding/base64"
"encoding/json"
"fmt"
)
type Oauth struct {
Aud string `json:"aud"`
Cid string `json:"cid"`
Exp int `json:"exp"`
Iat int `json:"iat"`
Iss string `json:"iss"`
Jti string `json:"jti"`
Scp []string `json:"scp"`
Sub string `json:"sub"`
UID string `json:"uid"`
Ver int `json:"ver"`
}
func main() {
encoded := "eyJ2ZXIiOjEsImp0aSI6IkFULnpndjlvUXB3LTdsM0JDZzZYYjVOQ0cyUGY4enhnaVFhMUVVQlh5Y21hRGsiLCJpc3MiOiJodHRwczovL2NvbXBhbnl4Lm9rdGEuY29tL29hdXRoMi9hdXMxYTRpYmRhdDBKWXc1czFkOCIsImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3QiLCJpYXQiOjE0ODQ1Mzg2MDYsImV4cCI6MTQ4NDU0MjIwNiwiY2lkIjoiM2ptTnZWQ0ZaNUY2bFdPeklPTk8iLCJ1aWQiOiIwMHV5NzRjMGg3TkdUTEJTWFFPQyIsInNjcCI6WyJyZWFkIiwicmVtb3ZlIiwicmVzZXJ2ZSJdLCJzdWIiOiJva3RhYWRtaW5Ab2t0YS5jb20ifQ"
// ✅ 使用 URLEncoding 解码 JWT Base64
data, err := base64.URLEncoding.DecodeString(encoded)
if err != nil {
panic("Base64 decode failed: " + err.Error())
}
fmt.Println("Decoded JSON:", string(data))
var x Oauth
// ✅ 必须检查 Unmarshal 错误!
err = json.Unmarshal(data, &x)
if err != nil {
panic("JSON unmarshal failed: " + err.Error())
}
fmt.Printf("Scp field: %+v\n", x.Scp) // 输出: Scp field: [read remove reserve]
}? 关键注意事项:
- JWT 的 Base64 编码严格遵循 Base64url(RFC 4648 §5),务必使用
base64.URLEncoding; -
json.Unmarshal在遇到语法错误(如缺失}、逗号错误、引号不匹配)时会返回具体错误,永远不要用_忽略它; - 若需解析真实 JWT,建议使用成熟库(如
github.com/golang-jwt/jwt/v5),它自动处理 Base64url 解码、签名验证与标准字段映射; - 结构体字段名首字母必须大写(已满足),且
jsontag 名需与 JSON 键完全一致(区分大小写)。
通过以上修正,Scp 字段将被正确填充为 ["read", "remove", "reserve"],彻底解决“数组不被识别”的问题。


















