У меня есть такая структура:
type Result struct {
Data MyStruct `json:"data,omitempty"`
Status string `json:"status,omitempty"`
Reason string `json:"reason,omitempty"`
}
Но даже если экземпляр MyStruct полностью пуст (то есть все значения по умолчанию), он сериализуется как:
"data":{}
Я знаю, что в документации по кодировке / json указано, что "пустыми" полями являются:
false, 0, любой указатель nil или значение интерфейса, а также любой массив, фрагмент, карта или строка нулевой длины
но без учета структуры со всеми пустыми значениями / значениями по умолчанию. Все его поля также помечены omitempty
, но это не влияет.
Как я могу заставить пакет JSON не маршалировать мое поле, которое является пустой структурой?
&MyStruct{ /* values */ }
считается нулевым указателем? Значение не равно нулю.Как @chakrit упоминались в комментариях, вы не можете получить эту работу по реализации
json.Marshaler
наMyStruct
и реализации функции сортировочной пользовательских JSON на каждую структуру , которая использует это может быть намного больше работы. Это действительно зависит от вашего варианта использования относительно того, стоит ли дополнительная работа или вы готовы жить с пустыми структурами в своем JSON, но вот шаблон, который я использую, применяется кResult
:type Result struct { Data MyStruct Status string Reason string } func (r Result) MarshalJSON() ([]byte, error) { return json.Marshal(struct { Data *MyStruct `json:"data,omitempty"` Status string `json:"status,omitempty"` Reason string `json:"reason,omitempty"` }{ Data: &r.Data, Status: r.Status, Reason: r.Reason, }) } func (r *Result) UnmarshalJSON(b []byte) error { decoded := new(struct { Data *MyStruct `json:"data,omitempty"` Status string `json:"status,omitempty"` Reason string `json:"reason,omitempty"` }) err := json.Unmarshal(b, decoded) if err == nil { r.Data = decoded.Data r.Status = decoded.Status r.Reason = decoded.Reason } return err }
Если у вас есть огромные структуры с множеством полей, это может стать утомительным, особенно изменение реализации структуры позже, но если
json
не считать переписывания всего пакета в соответствии с вашими потребностями (не очень хорошая идея), это в значительной степени единственный способ получить это сделано при сохранении не указателяMyStruct
.Кроме того, вам не обязательно использовать встроенные структуры, вы можете создавать именованные. Однако я использую LiteIDE с автозавершением кода, поэтому предпочитаю встроенный, чтобы избежать беспорядка.
источник
Data
- это инициализированная структура, поэтому она не считается пустой, потому чтоencoding/json
смотрит только на непосредственное значение, а не на поля внутри структуры.К сожалению, возврат
nil
изjson.Marhsler
текущего состояния не работает:func (_ MyStruct) MarshalJSON() ([]byte, error) { if empty { return nil, nil // unexpected end of JSON input } // ... }
Вы также можете дать
Result
маршалер, но это того не стоит.Единственный вариант, как предлагает Мэтт, - создать
Data
указатель и установить значение наnil
.источник
encoding/json
не могу проверить дочерние поля структуры. Да, это было бы не очень эффективно. Но это, конечно, не невозможно.json.Marshaler
в индивидуальном порядке.MyStruct
пуст , реализовавjson.Marshaler
наMyStruct
себя. Доказательство: play.golang.org/p/UEC8A3JGvxjson.Marshaler
сам содержащийResult
тип, что может быть очень неудобно.Есть замечательное предложение Golang для этой функции, которое действует уже более 4 лет, так что на данный момент можно с уверенностью предположить, что в ближайшее время она не войдет в стандартную библиотеку. Как отметил @Matt, традиционный подход заключается в преобразовании структур в указатели на структуры . Если такой подход невозможен (или непрактичен), то альтернативой является использование альтернативного кодировщика json, который поддерживает пропуск структур с нулевым значением .
Я создал зеркало библиотеки Golang json ( clarketm / json ) с добавленной поддержкой для исключения структур с нулевым значением при применении
omitempty
тега. Эта библиотека обнаруживает нули аналогично популярному кодировщику YAML go-yaml путем рекурсивной проверки полей общедоступной структуры .например
$ go get -u "github.com/clarketm/json"
import ( "fmt" "github.com/clarketm/json" // drop-in replacement for `encoding/json` ) type Result struct { Data MyStruct `json:"data,omitempty"` Status string `json:"status,omitempty"` Reason string `json:"reason,omitempty"` } j, _ := json.Marshal(&Result{ Status: "204", Reason: "No Content", }) fmt.Println(string(j))
// Note: `data` is omitted from the resultant json. { "status": "204" "reason": "No Content" }
источник