Валидация типа в json golang

Пишу http сервер, который принимает json. Есть структура:

type AuthModel struct {
    Username string
    Password string
}

Допустим пользователь отправляет такой json:

{
    "username": "user",
    "password": 1234
}

Задача его провалидировать и указать клиенту на его ошибки. После валидации я ожидаю получить: Invalid password type. Allow: string Или что-то подобное, неважно, главное чтобы было понятно в чём ошибка клиента.

Когда я пытаюсь распарсить этот json в структуру с помощью json.Unmarshal то сталкиваюсь с такой ошибкой: json: cannot unmarshal number into Go struct field AuthModel.password of type string. Не буду же я клиенту возвращать такой текст. Пытаться парсить его я думаю глупо (хотя если нет других способов...). Если я проигнорирую эту ошибку, то в структуре просто будет пустое поле password и не понятно проблема в том что оно было не того типа или просто не заполнено.

Как тут поступить? Есть готовые решения?


Ответы (2 шт):

Автор решения: antoshka

Переменная Password в структуре у вас типа string, а вы отправляете json с переменной Password с типом int.

1 Решение: Изменить структуру на:

type AuthModel struct {
    Username string
    Password int
}

2 Решение: Изменить отправляемый json:

{
    "username": "user",
    "password": "1234" //поместили в кавычки, теперь это переменная типа string и соответствует тому, что у вас стоит в структуре
}
→ Ссылка
Автор решения: Senior Pomidor


import (
    "encoding/json"
    "fmt"
    "log"
)

type AuthModel struct {
    Username string
    Password string
}

var data = `
{
    "username": "user",
    "password": 1234
}
`

func main() {
    var c AuthModel
    err := json.Unmarshal([]byte(data), &c)
    if err != nil {
        switch e := err.(type) {
        case *json.UnmarshalTypeError:
            log.Printf("UnmarshalTypeError: Value[%s] Type[%v]\n", e.Value, e.Type)
            retError := fmt.Errorf("Invalid json field[%s] type: got: %s, want: %v", e.Field, e.Value, e.Type)
            panic(retError)
        case *json.InvalidUnmarshalError:
            log.Printf("InvalidUnmarshalError: Type[%v]\n", e.Type)
        default:
            log.Println(err)
        }
    }

    fmt.Printf("%+v", c)
}


2021/08/30 10:50:22 UnmarshalTypeError: Value[number] Type[string]
panic: Invalid json field[Password] type: got: number, want: string

лучше всего в таких ситуациях просто возвращать http.StatusBadRequest, для валидации данных попробуйте go-playground/validator. validator позволяет валидировать входящие данные от пользователя, например, что пароль должен быть >10 символов

→ Ссылка