Назначение пустых полей 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/