Search code examples
jsongounmarshallingencoding-json-go

how to unmarshal json object if object is returning as empty string instead of empty struct


I'm receiving some data as JSON, but if a object is empty, it does not return a empty struct but a empty string instead, and when unmarshaling, it returns an error.

So instead of data being {"key":{}} is {"key":""}} , it does not work even using omitempty field

Example: https://play.golang.org/p/N1iuWBxuo1C

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)
}

Solution

  • You can have your item type implement the json.Unmarshaler interface.

    func (i *item) UnmarshalJSON(data []byte) error {
        if string(data) == `""` {
            return nil
        }
    
        type tmp item
        return json.Unmarshal(data, (*tmp)(i))
    }
    

    https://play.golang.org/p/1TrD57XULo9