我以JSON的形式接收一些数据,但是如果一个对象是空的,它不会返回一个空的结构,而是返回一个空的字符串,而且在解压缩的时候,会返回一个错误。
所以数据不是以 {"key":{}}
是 {"key":""}}
即使使用省略字段也不能工作。
例子。https:/play.golang.orgpN1iuWBxuo1C
type Store struct {
Title string `json:"title,omitempty"`
Item item `json:"item,omitempty"`
}
type item struct {
Price float32 `json:"price,omitempty"`
Kind string `json:"kind,omitempty"`
}
func main() {
var data1 Store
json1 := []byte(`{"title":"hello world","item":{"price":45.2,"kind":"fruit"}}`)
if err := json.Unmarshal(json1, &data1); err != nil {
log.Println("1, err: ", err)
return
}
log.Printf("data1: %+v\n", data1)
var data2 Store
json2 := []byte(`{"title":"hello world","item":{}}`)
if err := json.Unmarshal(json2, &data2); err != nil {
log.Println("2, err: ", err)
return
}
log.Printf("data2: %+v\n", data2)
var data3 Store
json3 := []byte(`{"title":"hello world","item":""}`)
if err := json.Unmarshal(json3, &data3); err != nil {
log.Println("3, err: ", err)
return
}
log.Printf("data3: %+v\n", data3)
}
你可以让你的数据是{"key":{}... item
贯彻执行 json.Unmarshaler
接口。
func (i *item) UnmarshalJSON(data []byte) error {
if string(data) == `""` {
return nil
}
type tmp item
return json.Unmarshal(data, (*tmp)(i))
}
创建一个类型,如 type ItemOrEmptyString item
并实现Unmarshal接口,让它来处理你的自定义案例。
func(ies *ItemOrEmptyString)UnmarshalJSON(d []byte) error{
var i item
if string(d) == `""` {
return nil
}
err := json.Unmarshal(d, &i)
*ies = ItemOrEmptyString(i)
return err
}
完整的代码 此处
这可能是一个品味问题,但 ""
是一个长度为零的字符串。不是一个空对象。JSON使用 null
来描述空的东西。这样就可以了。
json3 := []byte(`{"title":"hello world","item":null}`)
if err := json.Unmarshal(json3, &data3); err != nil {
log.Println("3, err: ", err)
return
}
就像... 文件 去。omitempty
是一个编码选项。
omitempty "选项指定了该字段应从"-"中省略。编码 如果字段的值为空,定义为false、0、nil指针、nil接口值,以及任何空数组、片断、映射或字符串。
json.Unmarshal
不指定任何使用 omitempty
标签。
如果你对输入没有控制权,可以使用一个接口类型,一个 型开关 和 类型断言:
type Store struct {
Title string `json:"title,omitempty"`
Item item `json:"item,omitempty"`
}
type item struct {
Price float32 `json:"price,omitempty"`
Kind string `json:"kind,omitempty"`
}
func unmarshal(js []byte) (*Store, error) {
var data = struct { // Intermediate var for unmarshal
Title string
Item interface{}
}{}
if err := json.Unmarshal(js, &data); err != nil {
return nil, err
}
s := &Store{Title: data.Title}
switch item := data.Item.(type) { // type switch
case string, nil:
return s, nil // Item remains empty
case map[string]interface{}:
p, ok := item["price"].(float64) // assertion
if ok {
s.Item.Price = float32(p)
}
s.Item.Kind, _ = item["kind"].(string) // _ prevents panic
return s, nil
default:
return nil, errors.New("Unknown type")
}
}
func main() {
jsons := [][]byte{
[]byte(`{"title":"hello world","item":{"price":45.2,"kind":"fruit"}}`),
[]byte(`{"title":"hello world","item":{}}`),
[]byte(`{"title":"hello world","item":""}`),
[]byte(`{"title":"hello world","item":null}`),
}
for i, js := range jsons {
data, err := unmarshal(js)
if err != nil {
log.Println("1, err: ", err)
return
}
log.Printf("data %d: %+v\n", i, data)
}
}