Назначение пустых полей JSON вместо пустых строк
Так как пустая строка является нулевым значением по умолчанию для Go string
, я решил определить все такие поля как interface{}
. например
type student struct {
FirstName interface{} 'json:"first_name"'
MiddleName interface{} 'json:"middle_name"'
LastName interface{} 'json:"last_name"'
}
Приложение, которое я отправляю мои данные, ожидает пустую строку вместо пустой, если значение не доступно для этого конкретного поля.
Это правильный подход или кто-то может указать мне что-то лучше, чем это.
Ответы
Ответ 1
В документации пакета json:
Значения указателя кодируются как значение, на которое указывает. Указатель nil кодируется как нулевой объект JSON.
Таким образом, вы можете сохранить указатель на строку, которая будет закодирована как строка, если не равна nil, и будет закодирована как "null", если nil
type student struct {
FirstName *string `json:"first_name"`
MiddleName *string `json:"middle_name"`
LastName *string `json:"last_name"`
}
Ответ 2
Может быть использован https://github.com/guregu/null
type student struct {
FirstName null.String 'json:"first_name"'
MiddleName null.String 'json:"middle_name"'
LastName null.String 'json:"last_name"'}
Ответ 3
Другой способ - это обходной путь с использованием метода интерфейса MarhshalJSON и UnmarshalJSON, предлагаемого библиотекой json lib of golang. Код как ниже:
type MyType string
type MyStruct struct {
A MyType 'json:"my_type"'
}
func (c MyType) MarshalJSON() ([]byte, error) {
var buf bytes.Buffer
if len(string(c)) == 0 {
buf.WriteString('null')
} else {
buf.WriteString('"' + string(c) + '"') // add double quation mark as json format required
}
return buf.Bytes(), nil
}
func (c *MyType)UnmarshalJSON(in []byte) error {
str := string(in)
if str == 'null' {
*c = ""
return nil
}
res := MyType(str)
if len(res) >= 2 {
res = res[1:len(res)-1] // remove the wrapped qutation
}
*c = res
return nil
}
тогда при использовании json.Marshal значение MyType будет маршалировано как ноль.
Ответ 4
В случае объекта json с нулевыми строками проще всего использовать опущенный декоратор в поле.
type student struct {
FirstName string 'json:"first_name,omitempty"'
MiddleName string 'json:"middle_name,omitempty"'
LastName string 'json:"last_name"'
}
В приведенном выше объявлении только ключ first_name будет отображаться в результирующем json. last_name, с другой стороны, всегда будет отображаться в результате со значением "", если оно не присвоено.
Теперь, когда вы начинаете включать числовые поля, где 0 может быть значением, использование omitempty не дает ожидаемого результата. Значение 0 всегда опускает поле, и нам необходимо различать значение 0 и неназначенное значение. Здесь может быть целесообразно использовать библиотеку, такую как https://github.com/guregu/null
.
Больше обсуждения здесь: https://www.sohamkamani.com/blog/golang/2018-07-19-golang-omitempty/