Можно ли указать пакету json, что при отсутствии определенного поля в документе метод NewDecoder().Decode() возвращал ошибку?

У меня есть вот такая структурка

type Request struct{
    Email string `json:"email"`
    Password string `json:"password"`
}

Я декодирую в нее json, можно ли указать, чтоб при отсутствии одного из полей, метод

request := Request{}
err := json.NewDecoder(r.Body).Decode(&request)

Возвращал ошибку?


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

Автор решения: Senior Pomidor

можно переопределить метод UnmarshalJSON(b []byte) error


import (
    "encoding/json"
    "fmt"
    "strings"
    "testing"

    "github.com/stretchr/testify/require"
)

type Request struct {
    Email    string `json:"email"`
    Password string `json:"password"`
}

func (this *Request) UnmarshalJSON(b []byte) error {
    type alias Request
    var a alias
    err := json.Unmarshal(b, &a)
    if err != nil {
        return err
    }

    if a.Email == "" {
        return fmt.Errorf("email cannot be empty")
    }

    this = &Request{
        Email:    a.Email,
        Password: a.Password,
    }
    return nil
}


func TestEncoder(t *testing.T) {
    str := `{"email":"","password":"not empty"}`
    dec := json.NewDecoder(strings.NewReader(str))

    var rr Request
    err := dec.Decode(&rr)
    require.NoError(t, err)
}

а если структура более сложная, то лучше использовать валидатор, где validate:"required" означает, что поле не пустое.


import (
    "encoding/json"
    "fmt"
    "strings"
    "testing"

    "github.com/go-playground/validator"
    "github.com/stretchr/testify/require"
)

type Request struct {
    Email    string `json:"email" validate:"required"`
    Password string `json:"password"`
}

func TestValidator(t *testing.T) {
    r := Request{
        Email:    "",
        Password: "not empty",
    }
    validator := validator.New()

    err := validator.Struct(r)
    require.Error(t, err)

    t.Logf("validation failed: %v", err)
}

→ Ссылка