解组 JSON 字段名称未知但结构已知

Go unmarshal JSON with unknown field name but known struct

我从 traefik tls 中检索了一个 acme.json,其中 traefik 存储 ssl/tls 证书信息。

现在我想用 golang 将 acme.json 解组到我的 go 结构“Traefik”中。但是我不知道如何处理 dynamic/unknown json 字段名称,因为 certificateresolver1certificateresolver2 是我在编译时不知道的名称。这些名称应该是在 go 中动态配置的。

我知道 json 的结构(它总是相同的)但不知道 certificateresolver 的字段名称。

有谁知道最好的方法吗?

Traefik acme.json

{
  "certificateresolver1": {
    "Account": {
      "Email": "email@example.com",
      "Registration": {
        "body": {
          "status": "valid",
          "contact": [
            "mailto:email@example.com"
          ]
        },
        "uri": "https://acme-v02.api.letsencrypt.org/acme/acct/124448363"
      },
      "PrivateKey": "PRIVATEKEY",
      "KeyType": "4096"
    },
    "Certificates": [
      {
        "domain": {
          "main": "example.com",
          "sans": [
            "test.example.com"
          ]
        },
        "certificate": "CERTIFICATE",
        "key": "KEY",
        "Store": "default"
      },
      {
        "domain": {
          "main": "example.org"
        },
        "certificate": "CERTIFICATE",
        "key": "KEY",
        "Store": "default"
      }
    ]
  },
  "certificateresolver2": {
    "Account": {
      "Email": "email@example.com",
      "Registration": {
        "body": {
          "status": "valid",
          "contact": [
            "mailto:email@example.com"
          ]
        },
        "uri": "https://acme-v02.api.letsencrypt.org/acme/acct/126945414"
      },
      "PrivateKey": "PRIVATEKEY",
      "KeyType": "4096"
    },
    "Certificates": [
      {
        "domain": {
          "main": "example.net"
        },
        "certificate": "CERTIFICATE",
        "key": "KEY",
        "Store": "default"
      }
    ]
  }
}

为 acme.json

构建结构
type Traefik struct {
    Provider []struct {
        Account struct {
            Email        string `json:"Email"`
            Registration struct {
                Body struct {
                    Status  string   `json:"status"`
                    Contact []string `json:"contact"`
                } `json:"body"`
                URI string `json:"uri"`
            } `json:"Registration"`
            PrivateKey string `json:"PrivateKey"`
            KeyType    string `json:"KeyType"`
        } `json:"Account"`
        Certificates []struct {
            Domain struct {
                Main string   `json:"main"`
                Sans []string `json:"sans"`
            } `json:"domain"`
            Certificate string `json:"certificate"`
            Key         string `json:"key"`
            Store       string `json:"Store"`
        } `json:"Certificates"`
    } `json:"certificateresolver"` <-- What to write there? It should fit for certificateresolver1 and certificateresolver2
}

我认为这样的事情会对你有所帮助:

type ProviderMdl map[string]Provider

type Provider struct {
    Account struct {
        Email        string `json:"Email"`
        Registration struct {
            Body struct {
                Status  string   `json:"status"`
                Contact []string `json:"contact"`
            } `json:"body"`
            URI string `json:"uri"`
        } `json:"Registration"`
        PrivateKey string `json:"PrivateKey"`
        KeyType    string `json:"KeyType"`
    } `json:"Account"`
    Certificates []struct {
        Domain struct {
            Main string   `json:"main"`
            Sans []string `json:"sans"`
        } `json:"domain"`
        Certificate string `json:"certificate"`
        Key         string `json:"key"`
        Store       string `json:"Store"`
    } `json:"Certificates"`
}

所以你可以这样处理这些数据:

    bres := new(ProviderMdl)
    if err := json.Unmarshal(data, bres); err != nil {
        panic(err)
    }
    
    // fmt.Printf("%+v - \n", bres)

    for key, value := range *bres {
        fmt.Printf("%v - %v\n", key, value)
    }

完整示例here