Golang如何将没有键值对的数组解析为结构体?

huangapple go评论87阅读模式
英文:

Golang unmarshal array without key/value to stuct

问题

我正在尝试将来自Google Analytics API的JSON数组放入一个结构体中。

例如:

"rows": [
[
"female",
"18-24",
"1308"
],
[
"female",
"25-34",
"741"
]
]

通常情况下,我会有键/值对,这样我就可以使用json:"gender"来放置。但是这里没有与之关联的键,所以它要搜索的值会发生变化。

结构体应该是:

type Row struct {
Gender string json:"gender"
AgeRange string json:"blah"
Count string json:"blah"
}

如果我执行len(jResp.Rows),我可以看到它获取了所有12行/数组,但字段是空的。

英文:

I'm trying to place a json array into a struct from Google Analytics API.

EG:

"rows": [
	[
		"female",
		"18-24",
		"1308"
	],
	[
		"female",
		"25-34",
		"741"
	]
]

Typically I'd have key/value so I can put json:"gender" but there are no keys to associate with, so the values that it would search for change.

The struct would be:

type Row struct {
	Gender   string `json:"gender"`
	AgeRange string `json:"blah"`
	Count    string `json:"blah"`
}

If I do len(jResp.Rows) I can see that it's grabbing all twelve rows/arrays but the fields are empty.

答案1

得分: 1

我不认为使用encoding/json直接将该JSON解码为一个结构体切片是可能的,而不需要在你的Row类型上首先实现一个UnmarshalJSON方法。

func (r *Row) UnmarshalJSON(data []byte) error {
    var s []string
    if err := json.Unmarshal(data, &s); err != nil {
        return err
    }
    if len(s) >= 3 {
        r.Gender = s[0]
        r.AgeRange = s[1]
        r.Count = s[2]
    }
    return nil
}

// 确保它是一个指向Row的切片
type Resp struct {
    Rows []*Row `json:"rows"`
}

编辑:稍微修正了一下代码,使其能够编译。这里有一个可工作的示例:https://play.golang.org/p/eqVQj65xJv。

你也可以先将数据解码为一个字符串切片,然后循环遍历结果来构建你的结构体值。

type Resp struct {
    Rows [][]string `json:"rows"`
}

type Row struct {
    Gender   string `json:"gender"`
    AgeRange string `json:"blah"`
    Count    string `json:"blah"`
}

var resp Resp
if err := json.Unmarshal(data, &resp); err != nil {
    panic(err)
}

var rows = make([]Row, len(resp.Rows))
for i, r := range resp.Rows {
    rows[i] = Row{
        Gender:   r[0],
        AgeRange: r[1],
        Count:    r[2],
    }
}

编辑:也修正了这个。https://play.golang.org/p/Otb7iULSh3

英文:

I don't think it's possible, with encoding/json to directly decode that json into a slice of structs without first implementing a UnmarshalJSON method on your Row type.

func (r *Row) UnmarshalJSON(data []byte) error {
     var s []string
     if err := json.Unmarshal(data, &s); err != nil {
          return err
     }
     if len(s) >= 3 {
         r.Gender = s[0]
         r.AgeRange = s[1]
         r.Count = s[2]
     }
     return nil
}

// make sure it's a slice of pointers to Row
type Resp struct {
    Rows []*Row `json:"rows"`
}

Edit: fixed the code a little to make it actually compile. Heres a working example https://play.golang.org/p/eqVQj65xJv.

You could also just decode the data first into a slice of strings and then loop over the result to build you struct values.

type Resp struct {
    Rows [][]string `json:"rows"`
}

type Row struct {
    Gender   string `json:"gender"`
    AgeRange string `json:"blah"`
    Count    string `json:"blah"`
}

var resp jResp
if err := json.Unmarshal(data, &resp); err != nil {
    panic(err)
}

var rows = make([]Row, len(resp.Rows))
for i, r := range resp.Rows {
    rows[i] = Row{
        Gender: r[0],
        AgeRange: r[1],
        Count: r[2],
    }
}

Edit: fixed this one as well. https://play.golang.org/p/Otb7iULSh3

huangapple
  • 本文由 发表于 2017年3月21日 07:54:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/42916088.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定