package handler import ( "encoding/json" "errors" "io" "net/http" "github.com/go-playground/validator/v10" "github.com/dbiz/cdp/data-layer/api/internal/apperr" ) var validate = validator.New(validator.WithRequiredStructEnabled()) // decodeAndValidate reads JSON into `dst`, then runs validator tags. Returns // a wrapped AppError so handlers can pass it straight to writeError. func decodeAndValidate(r *http.Request, dst any) error { dec := json.NewDecoder(r.Body) dec.DisallowUnknownFields() if err := dec.Decode(dst); err != nil { if errors.Is(err, io.EOF) { return apperr.BadRequest("request body is empty", "", err) } return apperr.BadRequest("invalid JSON: "+err.Error(), "", err) } if err := validate.Struct(dst); err != nil { var verrs validator.ValidationErrors if errors.As(err, &verrs) && len(verrs) > 0 { ve := verrs[0] return apperr.BadRequest("validation failed on "+ve.Field()+": "+ve.Tag(), ve.Field(), err) } return apperr.BadRequest("validation failed: "+err.Error(), "", err) } return nil }