英文:
Go Struct JSON array of arrays
问题
我正在尝试从特定的请求响应中映射一些数据,但在seriesLabels中有一些没有属性名称的数据(int,string),所以我对如何映射这些数据感到困惑:
这是服务的响应:
{
"data": {
"seriesLabels": [
[
0,
"(none)"
],
[
0,
"Cerveza"
],
[
0,
"Cigarros"
],
[
0,
"Tecate"
],
[
0,
"Cafe"
],
[
0,
"Amstel"
],
[
0,
"Leche"
],
[
0,
"Ultra"
],
[
0,
"Coca cola"
],
[
0,
"Agua"
]
]
}
}
我用以下go结构体来映射这些信息:
type PopularWord struct {
Data *Data json:"data"
}
type Data struct {
SeriesLabels []*SeriesLabels json:"seriesLabels"
}
type SeriesLabels struct {
value int32 json:""
name string json:""
}
我做错了什么?声明结构体的正确方式是什么?
英文:
I´m having problems trying to mapping some data from specific Request Response because inside seriesLabels: there are data without property names (int,string) so I'm confused how to map that data:
This is the service response:
{
"data": {
"seriesLabels": [
[
0,
"(none)"
],
[
0,
"Cerveza"
],
[
0,
"Cigarros"
],
[
0,
"Tecate"
],
[
0,
"Cafe"
],
[
0,
"Amstel"
],
[
0,
"Leche"
],
[
0,
"Ultra"
],
[
0,
"Coca cola"
],
[
0,
"Agua"
]
]
}
}
My go struct to map that info is:
type PopularWord struct {
Data *Data `json:"data"`
}
type Data struct {
SeriesLabels []*SeriesLabels `json:"seriesLabels"`
}
type SeriesLabels struct {
value int32 `json:""`
name string `json:""`
}
What am I doing wrong? What is the correct way to declare the structs?
答案1
得分: 2
问题是SeriesLabels
在JSON中表示为一个数组。如果你想使用encoding/json
,你需要实现Unmarshaler接口来解码它(否则它只会接受JSON对象)。
幸运的是,代码很简单:
func (s *SeriesLabels) UnmarshalJSON(d []byte) error {
arr := []interface{}{&s.value, &s.name}
return json.Unmarshal(d, &arr)
}
请注意,此代码忽略了无效的输入(数组过长或类型不正确)。根据你的需求,你可能希望在调用json.Unmarshal
之后添加检查,确保数组的长度和内容(指针)没有改变。
Go还有其他一些JSON解析库,可以使这个过程更加简便,比如gojay。
英文:
The problem is that SeriesLabels
is represented in JSON as an array. If you want to use encoding/json
, you have to implement the Unmarshaler interface to decode it (otherwise it will only accept JSON objects).
Fortunately, the code is simple:
func (s *SeriesLabels) UnmarshalJSON(d []byte) error {
arr := []interface{}{&s.value, &s.name}
return json.Unmarshal(d, &arr)
}
Note that this code ignores invalid input (array too long, or incorrect type). Depending on your needs, you may wish to add checks after the call to json.Unmarshal
that the array length and contents (pointers) have not changed.
There are other JSON parsing libraries for Go that make this a bit less cumbersome, like gojay.
答案2
得分: 2
seriesLabels
是一个 JSON 数组,其元素也是 JSON 数组。
要解析一个 JSON 数组的数组,你可以在 Go 中使用切片的切片:
type Data struct {
SeriesLabels [][]interface{}
}
测试代码:
var pw *PopularWord
if err := json.Unmarshal([]byte(src), &pw); err != nil {
panic(err)
}
fmt.Println(pw)
for _, sl := range pw.Data.SeriesLabels {
fmt.Println(sl)
}
输出结果(在 [Go Playground][1] 上尝试):
&{0xc000120108}
[0 (none)]
[0 Cerveza]
[0 Cigarros]
[0 Tecate]
[0 Cafe]
[0 Amstel]
[0 Leche]
[0 Ultra]
[0 Coca cola]
[0 Agua]
要将内部数组作为结构值获取,你可以实现自定义的解组:
type Data struct {
SeriesLabels []*SeriesLabels `json:"seriesLabels"`
}
type SeriesLabels struct {
value int32
name string
}
func (sl *SeriesLabels) UnmarshalJSON(p []byte) error {
var s []interface{}
if err := json.Unmarshal(p, &s); err != nil {
return err
}
if len(s) > 0 {
if f, ok := s[0].(float64); ok {
sl.value = int32(f)
}
}
if len(s) > 1 {
if s, ok := s[1].(string); ok {
sl.name = s
}
}
return nil
}
测试代码与之前相同,输出结果(在 [Go Playground][2] 上尝试):
&{0xc0000aa0f0}
&{0 (none)}
&{0 Cerveza}
&{0 Cigarros}
&{0 Tecate}
&{0 Cafe}
&{0 Amstel}
&{0 Leche}
&{0 Ultra}
&{0 Coca cola}
&{0 Agua}
[1]: https://play.golang.org/p/4slLP6So4Jv
[2]: https://play.golang.org/p/iVL-lH46Mer
<details>
<summary>英文:</summary>
`seriesLabels` is a JSON array, and its elements are also JSON arrays.
To parse a JSON array of arrays, you may use a slice of slices in Go:
type Data struct {
SeriesLabels [][]interface{}
}
Testing it:
var pw *PopularWord
if err := json.Unmarshal([]byte(src), &pw); err != nil {
panic(err)
}
fmt.Println(pw)
for _, sl := range pw.Data.SeriesLabels {
fmt.Println(sl)
}
Output (try it on the [Go Playground][1]):
&{0xc000120108}
[0 (none)]
[0 Cerveza]
[0 Cigarros]
[0 Tecate]
[0 Cafe]
[0 Amstel]
[0 Leche]
[0 Ultra]
[0 Coca cola]
[0 Agua]
To get the inner arrays as struct values, you may implement custom unmarshaling:
type Data struct {
SeriesLabels []*SeriesLabels `json:"seriesLabels"`
}
type SeriesLabels struct {
value int32
name string
}
func (sl *SeriesLabels) UnmarshalJSON(p []byte) error {
var s []interface{}
if err := json.Unmarshal(p, &s); err != nil {
return err
}
if len(s) > 0 {
if f, ok := s[0].(float64); ok {
sl.value = int32(f)
}
}
if len(s) > 1 {
if s, ok := s[1].(string); ok {
sl.name = s
}
}
return nil
}
Testing code is the same, output (try this one on the [Go Playground][2]):
&{0xc0000aa0f0}
&{0 (none)}
&{0 Cerveza}
&{0 Cigarros}
&{0 Tecate}
&{0 Cafe}
&{0 Amstel}
&{0 Leche}
&{0 Ultra}
&{0 Coca cola}
&{0 Agua}
[1]: https://play.golang.org/p/4slLP6So4Jv
[2]: https://play.golang.org/p/iVL-lH46Mer
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论