Go 将数组解组到结构中

Go 将数组解组到结构中,go,struct,type-conversion,Go,Struct,Type Conversion,我试图弄清楚如何(使用gin)从api调用创建一个结构 "icon": [ "https://api.figo.me/assets/images/accounts/postbank.png", { "48x48": "https://api.figo.me/assets/images/accounts/postbank_48.png", "60x60": "https://api.figo.me/assets/images/

我试图弄清楚如何(使用gin)从api调用创建一个结构

"icon": [
        "https://api.figo.me/assets/images/accounts/postbank.png",
        {
          "48x48": "https://api.figo.me/assets/images/accounts/postbank_48.png",
          "60x60": "https://api.figo.me/assets/images/accounts/postbank_60.png",
          "72x72": "https://api.figo.me/assets/images/accounts/postbank_72.png",
          "84x84": "https://api.figo.me/assets/images/accounts/postbank_84.png",
          "96x96": "https://api.figo.me/assets/images/accounts/postbank_96.png",
          "120x120": "https://api.figo.me/assets/images/accounts/postbank_120.png",
          "144x144": "https://api.figo.me/assets/images/accounts/postbank_144.png",
          "192x192": "https://api.figo.me/assets/images/accounts/postbank_192.png",
          "256x256": "https://api.figo.me/assets/images/accounts/postbank_256.png"
        }
      ],
进入

图标部分只是一个摘录,但我总是得到一个这部分的解组错误。我必须如何定义结构中的“图标”部分?

这将起作用

package main

type CatalogBank struct {
   Icon []interface{} `json:"icon"`
}

这在Golang中有点棘手,因为JSON中的类型不严格。如果这确实是您要接收数据的格式,那么您应该将其解组到
接口{}
,然后将该接口解析为一个可以在Golang中使用的结构

无法进行直接解组,因为每个字段的类型未知

type Icon struct{
    ImageLink string
    ImageLink48 string
    // ...
}

type CatalogBank struct {
    Advice      string `json:"advice"`
    IconRaw     []interface{} `json:"icon"`
    Icon        []Icon
    //...
}

func UnmarshalIcon(c &CatalogBank, i interface{}):
    // first convert it to the top level list
    newIcon := Icon{}
    listOfIcons := i.([]interface{})
    for _, i := range listOfIcons:
        switch iT := i.(type) {
           case string:
                newIcon.ImageLink = iT
           case map[string]interface{}:
              for smallIconsKey, smallIconLink := range iT {
                  if smallIconsKey == "48x48"{
                         newIcon.ImageLink48 = smallIconLink.(string)
                  }
                  // and so on
        }


var c CatalogBank{}
_ := json.Unmarshal([]byte(your_json), &c)
for _, i := range c.IconRaw:
   UnmarshalIcon(&c, i)

注意:我没有检查上面的实现,但它应该是这样的

您不能使用[]struct{}作为图标,将其改为[]interface{},或者如果您想对类型安全类型进行操作,请使用cusom unmarshaler查看第二个解决方案

解决方案1

解决方案2:

    package main

    import (
        "encoding/json"
        "fmt"
        "log"
    )

    type Icons struct {
        URL    string
        BySize map[string]string
    }



    type CatalogBank struct {
        Advice   string `json:"advice"`
        BankCode string `json:"bank_code"`
        BankName string `json:"bank_name"`
        BIC      string `json:"bic"`
        Credentials []struct {
            Label  string `json:"label"`
            Masked bool   `json:"masked"`
        } `json:"credentials"`
        Icon     *Icons `json:"-,"`
        Language []byte `json:"language"`
    }

    func (p *CatalogBank) Unmarshal(data []byte) error {


        type Transient struct {
            *CatalogBank
            Icon []interface{} `json:"icon"`
        }

        var transient = &Transient{CatalogBank:p}
        err := json.Unmarshal([]byte(data), transient)
        if err != nil {
            return err
        }
        p.Icon = &Icons{
            BySize: make(map[string]string),
        }

        if len(transient.Icon) > 0 {
            if url, ok := transient.Icon[0].(string); ok {
                p.Icon.URL = url
            }
            if aMap, ok := transient.Icon[1].(map[string]interface{}); ok {
                for k, v := range aMap {
                    p.Icon.BySize[k] = v.(string)
                }
            }
        }
        return nil
    }

    func main() {

        data := `
            {
            "Advice":"abc",
            "icon": [
                    "https://api.figo.me/assets/images/accounts/postbank.png",
                    {
                      "48x48": "https://api.figo.me/assets/images/accounts/postbank_48.png",
                      "60x60": "https://api.figo.me/assets/images/accounts/postbank_60.png",
                      "72x72": "https://api.figo.me/assets/images/accounts/postbank_72.png",
                      "84x84": "https://api.figo.me/assets/images/accounts/postbank_84.png",
                      "96x96": "https://api.figo.me/assets/images/accounts/postbank_96.png",
                      "120x120": "https://api.figo.me/assets/images/accounts/postbank_120.png",
                      "144x144": "https://api.figo.me/assets/images/accounts/postbank_144.png",
                      "192x192": "https://api.figo.me/assets/images/accounts/postbank_192.png",
                      "256x256": "https://api.figo.me/assets/images/accounts/postbank_256.png"
                    }
                  ]
            }
            `

        bank := &CatalogBank{}
        err := bank.Unmarshal([]byte(data))
        if err != nil {
            log.Fatal(err)
        }
        fmt.Printf("advice: %v\n", bank.Advice)

        fmt.Printf("icon: %v\n", bank.Icon.URL)
        for size, icon := range bank.Icon.BySize {
            fmt.Printf("%v =>  %v\n ",size, icon)
        }
    }

您可以这样定义您的图标:

包干管

import (
    "fmt"
    "encoding/json"
)

var testIcon = []byte(`{"icon":[
                        "https://api.figo.me/assets/images/accounts/postbank.png",
                        {
                            "48x48":"https://api.figo.me/assets/images/accounts/postbank_48.png"
                        }]
                    }`)

func main() {

    icon := make(map[string][]interface{})
    err := json.Unmarshal(testIcon, &icon)
    if err != nil {
        panic(err)
    }

    fmt.Println(icon)
    // map[icon:[https://api.figo.me/assets/images/accounts/postbank.png map[48x48:https://api.figo.me/assets/images/accounts/postbank_48.png]]]

}

你试过什么?您遇到了什么问题?另请参阅是否遇到错误“无效字符”:“顶级值之后”我可以参考此链接来解决问题。
    package main

    import (
        "encoding/json"
        "fmt"
        "log"
    )

    type Icons struct {
        URL    string
        BySize map[string]string
    }



    type CatalogBank struct {
        Advice   string `json:"advice"`
        BankCode string `json:"bank_code"`
        BankName string `json:"bank_name"`
        BIC      string `json:"bic"`
        Credentials []struct {
            Label  string `json:"label"`
            Masked bool   `json:"masked"`
        } `json:"credentials"`
        Icon     *Icons `json:"-,"`
        Language []byte `json:"language"`
    }

    func (p *CatalogBank) Unmarshal(data []byte) error {


        type Transient struct {
            *CatalogBank
            Icon []interface{} `json:"icon"`
        }

        var transient = &Transient{CatalogBank:p}
        err := json.Unmarshal([]byte(data), transient)
        if err != nil {
            return err
        }
        p.Icon = &Icons{
            BySize: make(map[string]string),
        }

        if len(transient.Icon) > 0 {
            if url, ok := transient.Icon[0].(string); ok {
                p.Icon.URL = url
            }
            if aMap, ok := transient.Icon[1].(map[string]interface{}); ok {
                for k, v := range aMap {
                    p.Icon.BySize[k] = v.(string)
                }
            }
        }
        return nil
    }

    func main() {

        data := `
            {
            "Advice":"abc",
            "icon": [
                    "https://api.figo.me/assets/images/accounts/postbank.png",
                    {
                      "48x48": "https://api.figo.me/assets/images/accounts/postbank_48.png",
                      "60x60": "https://api.figo.me/assets/images/accounts/postbank_60.png",
                      "72x72": "https://api.figo.me/assets/images/accounts/postbank_72.png",
                      "84x84": "https://api.figo.me/assets/images/accounts/postbank_84.png",
                      "96x96": "https://api.figo.me/assets/images/accounts/postbank_96.png",
                      "120x120": "https://api.figo.me/assets/images/accounts/postbank_120.png",
                      "144x144": "https://api.figo.me/assets/images/accounts/postbank_144.png",
                      "192x192": "https://api.figo.me/assets/images/accounts/postbank_192.png",
                      "256x256": "https://api.figo.me/assets/images/accounts/postbank_256.png"
                    }
                  ]
            }
            `

        bank := &CatalogBank{}
        err := bank.Unmarshal([]byte(data))
        if err != nil {
            log.Fatal(err)
        }
        fmt.Printf("advice: %v\n", bank.Advice)

        fmt.Printf("icon: %v\n", bank.Icon.URL)
        for size, icon := range bank.Icon.BySize {
            fmt.Printf("%v =>  %v\n ",size, icon)
        }
    }
import (
    "fmt"
    "encoding/json"
)

var testIcon = []byte(`{"icon":[
                        "https://api.figo.me/assets/images/accounts/postbank.png",
                        {
                            "48x48":"https://api.figo.me/assets/images/accounts/postbank_48.png"
                        }]
                    }`)

func main() {

    icon := make(map[string][]interface{})
    err := json.Unmarshal(testIcon, &icon)
    if err != nil {
        panic(err)
    }

    fmt.Println(icon)
    // map[icon:[https://api.figo.me/assets/images/accounts/postbank.png map[48x48:https://api.figo.me/assets/images/accounts/postbank_48.png]]]

}