Это может быть дело вкуса, но ""
- строка нулевой длины. Не пустой объект. 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, нулевой указатель, нулевое значение интерфейса и любой пустой массив, срез, карту или строку.
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.org/p/Dnq1ZVfGPE7