在一个切片中解组2个不同的结构

时间:2018-02-09 02:40:46

标签: arrays go struct

我的输入json数据是这样的(无法从外部资源更改):

[{
   "Url": "test.url",
   "Name": "testname"
},{ 
   "FormName": "Test - 2018",
   "FormNumber": 43,
   "FormSlug": "test-2018"
}]

我有两个总是匹配数组中数据的结构:

type UrlData struct{
  "Url"  string `json:Url` 
  "Name" string `json:Name` 
}

type FormData struct{
  "FormName"  string `json:FormName` 
  "FormNumber" string `json:FormNumber` 
  "FormSlug" string `json:FormSlug`
}

显然下面的代码不起作用,但是可以在顶层(或其他方面)声明这样的代码:

type ParallelData [
 urlData UrlData
 formData FormData
]

3 个答案:

答案 0 :(得分:9)

使用两步处理进行解组。首先,解组任意JSON列表,然后将该列表的第一个和第二个元素解组为各自的类型。

您可以在名为UnmarshalJSON的方法中实现该逻辑,从而实现the json.Unmarshaler interface。这将为您提供您正在寻找的复合类型:

type ParallelData struct {
    UrlData  UrlData
    FormData FormData
}

// UnmarshalJSON implements json.Unmarshaler.
func (p *ParallelData) UnmarshalJSON(b []byte) error {
    var records []json.RawMessage
    if err := json.Unmarshal(b, &records); err != nil {
        return err
    }

    if len(records) < 2 {
        return errors.New("Short JSON array")
    }

    if err := json.Unmarshal(records[0], &p.UrlData); err != nil {
        return err
    }

    if err := json.Unmarshal(records[1], &p.FormData); err != nil {
        return err
    }

    return nil
}

在操场上试试:https://play.golang.org/p/QMn_rbJj-P-

答案 1 :(得分:4)

我认为Answer of Peter非常棒。

选项1:

type ParallelData [
 urlData UrlData
 formData FormData
]

如果您需要以上结构,那么您可以将其定义为

type UrlData struct {
    Url  string `json:"Url,omitempty"`
    Name string `json:"Name,omitempty"`
}
type FormData struct {
    FormName   string `json:"FormName,omitempty"`
    FormNumber string `json:"FormNumber,omitempty"`
    FormSlug   string `json:"FormSlug,omitempty"`
}
type ParallelData struct {
    UrlData  UrlData  `json:"UrlData,omitempty"`
    FormData FormData `json:"FormData,omitempty"`
}

在这种情况下,你的json看起来像

[  
   {  
      "UrlData":{  
         "Url":"test.url",
         "Name":"testname"
      }
   },
   {  
      "FormData":{  
         "FormName":"Test - 2018",
         "FormNumber":"43",
         "FormSlug":"test-2018"
      }
   }
]

选项2:

您提供了以下json:

[  
   {  
      "Url":"test.url",
      "Name":"testname"
   },
   {  
      "FormName":"Test - 2018",
      "FormNumber":43,
      "FormSlug":"test-2018"
   }
]

如果您的json看起来很像,那么您可以使用以下struct

type UrlData struct {
    Url  string `json:Url`
    Name string `json:Name`
}

type FormData struct {
    FormName   string `json:FormName`
    FormNumber int    `json:FormNumber`
    FormSlug   string `json:FormSlug`
}

type ParallelData struct {
    UrlData
    FormData
}

对于这两个选项,您可以像这样解组你的json

var parallelData []ParallelData
err := json.Unmarshal([]byte(str), &parallelData)
if err != nil {
    panic(err)
}
fmt.Println(parallelData)

参见 playground

中的选项1

参见 playground

中的选项2

答案 2 :(得分:1)

您可以解组为map[string]interface{},例如:

type ParallelData map[string]interface{}

func main() {
    textBytes := []byte(`[
    {
      "Url": "test.url",
      "Name": "testname" 
    },
    {
      "FormName": "Test - 2018",
      "FormNumber": 43,
      "FormSlug": "test-2018"
    }]`)
    var acc []ParallelData
    json.Unmarshal(textBytes, &acc)

    fmt.Printf("%+v", acc)
}

输出:

=> [map[Url:test.url Name:testname] map[FormName:Test - 2018 FormNumber:43 FormSlug:test-2018]]

<子> Playground