如果对象返回的是空字符串而不是空结构体,如何解除json对象的marshal。

问题描述 投票:1回答:1

我以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)
}
json go unmarshalling
1个回答
3
投票

你可以让你的数据是{"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))
}

https:/play.golang.orgp1TrD57XULo9。


2
投票

创建一个类型,如 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
}

完整的代码 此处


1
投票

这可能是一个品味问题,但 "" 是一个长度为零的字符串。不是一个空对象。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)
    }
}

https:/play.golang.orgpDnq1ZVfGPE7。

© www.soinside.com 2019 - 2024. All rights reserved.