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

Go语言解析含不同字段的JSON数组,提取首个元素的方法

问题分析与解决方法

核心问题

  1. 结构不匹配:你的JSON最外层是包含Secrets数组的对象,但代码直接将整个JSON反序列化到model结构体,两者结构完全不匹配,导致所有字段都是零值,输出为空。
  2. Secret字段结构多样:Secrets数组中不同元素的secret字段结构不同(一种包含tlsCertificate,另一种包含validationContext),需要兼容这两种结构。

解决步骤

1. 定义外层结构体匹配JSON结构

首先需要定义一个对应JSON最外层的结构体,用来承载Secrets数组:

type Response struct {
    Secrets []model `json:"Secrets"`
}

2. 修改model兼容两种Secret结构

Go的JSON反序列化会忽略结构体中不存在的JSON字段,因此可以在Secret结构体中同时声明两种可能的字段:

type model struct {
    Name        string    `json:"name"`
    VersionInfo string    `json:"versionInfo"` // 原格式带`/1`后缀,无法直接解析为time.Time,先存为字符串
    LastUpdated time.Time `json:"lastUpdated"`
    Secret      struct {
        Type              string `json:"@type"`
        Name              string `json:"name"`
        // 对应第一个元素的Secret结构
        TLSCertificate    struct {
            CertificateChain struct {
                InlineBytes string `json:"inlineBytes"`
            } `json:"certificateChain"`
            PrivateKey struct {
                InlineBytes string `json:"inlineBytes"`
            } `json:"privateKey"`
        } `json:"tlsCertificate"`
        // 对应第二个元素的Secret结构(仅用于兼容,不影响第一个元素的解析)
        ValidationContext struct {
            TrustedCa struct {
                InlineBytes string `json:"inlineBytes"`
            } `json:"trustedCa"`
        } `json:"validationContext"`
    } `json:"secret"`
}

3. 修改反序列化逻辑,提取第一个元素

在main函数中先反序列化到外层结构体,再取出数组中的第一个元素:

func main() {
    input := []byte(jsondata)
    var resp Response
    err := json.Unmarshal(input, &resp)
    if err != nil {
        panic(err)
    }

    // 检查数组是否为空
    if len(resp.Secrets) == 0 {
        fmt.Println("未找到任何Secrets数据")
        return
    }

    // 获取第一个元素并输出所需字段
    firstSecret := resp.Secrets[0]
    fmt.Printf("名称: %s\n", firstSecret.Name)
    fmt.Printf("Secret名称: %s\n", firstSecret.Secret.Name)
    fmt.Printf("证书链: %s\n", firstSecret.Secret.TLSCertificate.CertificateChain.InlineBytes)
    fmt.Printf("私钥: %s\n", firstSecret.Secret.TLSCertificate.PrivateKey.InlineBytes)
}

可选:将versionInfo解析为time.Time

如果需要把带/1后缀的versionInfo转为time.Time,可以自定义结构体的反序列化方法:

import "strings"

func (m *model) UnmarshalJSON(data []byte) error {
    // 定义临时结构体用于临时存储数据
    type tempModel struct {
        Name        string    `json:"name"`
        VersionInfo string    `json:"versionInfo"`
        LastUpdated time.Time `json:"lastUpdated"`
        Secret      struct {
            Type              string `json:"@type"`
            Name              string `json:"name"`
            TLSCertificate    struct {
                CertificateChain struct {
                    InlineBytes string `json:"inlineBytes"`
                } `json:"certificateChain"`
                PrivateKey struct {
                    InlineBytes string `json:"inlineBytes"`
                } `json:"privateKey"`
            } `json:"tlsCertificate"`
            ValidationContext struct {
                TrustedCa struct {
                    InlineBytes string `json:"inlineBytes"`
                } `json:"trustedCa"`
            } `json:"validationContext"`
        } `json:"secret"`
    }

    var t tempModel
    if err := json.Unmarshal(data, &t); err != nil {
        return err
    }

    // 截取`/`之前的时间字符串并解析
    if idx := strings.Index(t.VersionInfo, "/"); idx != -1 {
        t.VersionInfo = t.VersionInfo[:idx]
    }
    versionTime, err := time.Parse(time.RFC3339, t.VersionInfo)
    if err != nil {
        return err
    }

    // 将临时结构体的数据赋值给原结构体
    m.Name = t.Name
    m.VersionInfo = versionTime
    m.LastUpdated = t.LastUpdated
    m.Secret = t.Secret
    return nil
}

此时将model中的VersionInfo类型改回time.Time即可:

VersionInfo time.Time `json:"versionInfo"`

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 11:20:56