Как игнорировать поля JSON, когда маршалинг не демаршаллинг

Предположим, у меня есть поле пароля в структуре пользователя.

type User struct{
   UserName string 'json:"username"'
   Password string 'json:"-"'
}

Мои клиенты регистрируют своих пользователей, отправляя имя пользователя и пароль вместе. Поэтому, если я декодирую JSON до структуры выше, он игнорирует пароль. Это ожидалось. Но я подумал, есть ли способ игнорировать поля, когда они только сортируются. Я проверил страницу официальной документации, но ничего не нашел.

https://golang.org/pkg/encoding/json/

Я могу добавить дополнительное поле в структуру, но сначала мне нужно знать, возможно ли это сделать с помощью JSON lib.

Ответ 1

Один общий подход - использовать временный тип или переменную с той же структурой, но разные json теги или даже другую структуру:

type User struct {
    UserName string 'json:"username"'
    Password string 'json:"password"'
}

func (usr User) MarshalJSON() ([]byte, error) {
    var tmp struct {
        UserName string 'json:"username"'
    }
    tmp.UserName = usr.UserName
    return json.Marshal(&tmp)
}

Ответ 2

Как и в случае любых пользовательских требований маршалинга/демаршалинга в Go, лучше всего взглянуть на реализацию интерфейса json.Marshaler/json.Unmarshaler для пользовательского типа.

В этом случае вы можете сделать это для поля пароля:

// Use an explicit password type.
type password string

type User struct{
    UserName string   'json:"username"'
    Password password 'json:"password"'
}

// Marshaler ignores the field value completely.
func (password) MarshalJSON() ([]byte, error) {
    return []byte('""'), nil
}

Обратите внимание, что, не реализуя json.Unmarshaler, тип password сохраняет поведение по умолчанию своего базового типа (string), что позволяет демонтировать структуру со значением Password.

Рабочий пример: https://play.golang.org/p/HZQoCKm0vN

Ответ 3

Я предпочитаю тип композиции. Например:

type User struct {
    UserName string 'json:"username"'
}

type UserWithPassword struct {
    *User
    Password string 'json:"password"'
}

используйте UserWithPassword при получении данных (например, создание/изменение пользователя) и User при их возврате (аутентификация).