我需要一些解组的帮助。我有这个示例代码:
package main
import (
"encoding/json"
"fmt"
)
type Obj struct {
Id string `json:"id"`
Data []byte `json:"data"`
}
func main() {
byt := []byte(`{"id":"someID","data":["str1","str2"]}`)
var obj Obj
if err := json.Unmarshal(byt, &obj); err != nil {
panic(err)
}
fmt.Println(obj)
}
我在这里尝试做什么 - 将字节转换为结构,其中一个字段的类型为 [] byte 。我得到的错误:
恐慌:json:无法将字符串解组成Go结构字段Obj.data 输入uint8
这可能是因为解析器已经看到“data”字段已经是一个切片并试图将“str1”表示为一些char字节码(类型为uint8?)。
如何将整个数据值存储为一个字节数组?因为我想稍后将值解组为字符串片段。我没有在struct中包含一段字符串,因为这种类型可以改变(字符串数组,int,string等),我希望这是通用的。
答案 0 :(得分:3)
如果您知道输入类型将是一个字符串数组,那么我的第一个建议是让您只使用[]string
而不是[]byte
。
如果data
将成为具有各种类型的JSON数组,那么您最好的选择是使用[]interface{}
- Go会很乐意为您解组JSON,并且您可以在运行时执行检查根据需要将它们转换为更具体的类型变量。
答案 1 :(得分:2)
如果您想要[]byte
,请使用json.RawMessage
,其中 类型为[]byte
,但也会实施JSON解析的方法。我相信这可能是你想要的,因为它会接受data
中的任何结果。当然,您必须手动解析Data
以确定实际存在的内容。
一个可能的好处是,它会跳过任何繁重的解析,因为它只会复制byte
。如果要将此数据用于某些内容,请使用[]interface{}
,然后使用类型开关来使用单个值。
https://play.golang.org/p/og88qb_qtpSGJ
package main
import (
"encoding/json"
"fmt"
)
type Obj struct {
Id string `json:"id"`
Data json.RawMessage `json:"data"`
}
func main() {
byt := []byte(`{"id":"someID","data":["str1","str2", 1337, {"my": "obj", "id": 42}]}`)
var obj Obj
if err := json.Unmarshal(byt, &obj); err != nil {
panic(err)
}
fmt.Printf("%+v\n", obj)
fmt.Printf("Data: %s\n", obj.Data)
// use it
var d []interface{}
if err := json.Unmarshal(obj.Data, &d); err != nil {
panic(err)
}
fmt.Printf("%+v\n", d)
for _, v := range d {
// you need a type switch to deterine the type and be able to use most of these
switch real := v.(type) {
case string:
fmt.Println("I'm a string!", real)
case float64:
fmt.Println("I'm a number!", real)
default:
fmt.Printf("Unaccounted for: %+v\n", v)
}
}
}
答案 2 :(得分:0)
你的问题是:
使用[] byte
类型的字段将bytes数组转换为struct
但是你没有bytearray而是字符串数组。你的问题与你的例子不一样。所以,回答你的问题,根据你想要偏离原始要求的程度,可以有更多的解决方案。
一个字符串可以转换为一个字节切片,首先需要将两个字符串转换为一个字符串。这就是问题所在。第二个问题是你的json-string
中的方括号这很好用,它会隐式地将json-string中的字符串转换为字节切片:
byt := []byte(`{"id":"someID","data":"str1str2"}`)
var obj Obj
if err := json.Unmarshal(byt, &obj); err != nil {
panic(err)
}
fmt.Println(obj)