Примитивные типы данных Go не подходят для обработки "всех допустимых значений", и дополнительная информация "присутствует".
Если вам это нужно, одним из способов является использование указателей, где nil
значение указателя соответствует «отсутствующему» состоянию.
Если впоследствии работать с указателями неудобно, выполните «постобработку»: преобразуйте свои структуры с полями указателя в значение структуры с полями без указателя,так что вы можете работать с этим позже.
Вы можете сделать это «вручную» или написать собственный демаршалер, чтобы это произошло автоматически.
Вот пример, как это сделать:
type PCar struct {
Name *string `json:"name"`
Speed *int `json:"speed"`
}
type Car struct {
Name string `json:"-"`
Speed int `json:"-"`
PCar
}
func (c *Car) UnmarshalJSON(data []byte) error {
if err := json.Unmarshal(data, &c.PCar); err != nil {
return err
}
if c.PCar.Name != nil {
c.Name = *c.PCar.Name
}
if c.PCar.Speed != nil {
c.Speed = *c.PCar.Speed
}
return nil
}
Пример использования:
sources := []string{
`{"name": "", "speed": 0}`,
`{}`,
`{"name": "Bob", "speed": 21}`,
}
for i, src := range sources {
var c Car
if err := json.Unmarshal([]byte(src), &c); err != nil {
panic(err)
}
fmt.Println("car", i, c)
}
Вывод (попробуйте на Go Playground ):
car 0 { 0 {0x40c200 0x4140ac}}
car 1 { 0 {<nil> <nil>}}
car 2 {Bob 21 {0x40c218 0x41410c}}
Как видите,car 1
содержит 2 не nil
указателя, потому что соответствующие поля присутствовали во входном JSON, в то время как car 2
содержит 2 nil
указателей, потому что эти поля отсутствовали во входных данных.Вы можете использовать поля Car.Name
и Car.Speed
как не указатели (потому что они не указатели).Чтобы узнать, присутствовали ли они на входе, вы можете проверить соответствующие указатели Car.PCar.Name
и Car.PCar.Speed
, если они nil
.