learningtech
learningtech

Reputation: 33695

Go validator with sql null types?

I am having problems getting the golang validator to work with SQL null types. Here's an example of what I tried:

package main

import (
    "database/sql"
    "database/sql/driver"
    "log"

    "gopkg.in/go-playground/validator.v9"
)

// NullInt64
type NullInt64 struct {
    sql.NullInt64
    Set bool
}

func MakeNullInt64(valid bool, val int64) NullInt64 {
    n := NullInt64{}
    n.Set = true
    n.Valid = valid
    if valid {
        n.Int64 = val
    }
    return n
}
func (n *NullInt64) Value() (driver.Value, error) {
    if !n.NullInt64.Valid {
        return nil, nil
    }
    return n.NullInt64.Int64, nil
}

type Thing struct {
    N2 NullInt64 `validate:"min=10"`
    N3 int64     `validate:"min=10"`
    N4 *int64    `validate:"min=10"`
}

func main() {
    validate := validator.New()

    n := int64(6)
    number := MakeNullInt64(true, n)
    thing := Thing{number, n, &n}
    e := validate.Struct(thing)

    log.Println(e)
}

When I run this code, I only get this output:

Key: 'Thing.N3' Error:Field validation for 'N3' failed on the 'min' tag

Key: 'Thing.N4' Error:Field validation for 'N4' failed on the 'min' tag

The problem is that I want it to also show that Thing.N2 failed for the same reasons as Thing.N3 and Thing.N4.

I tried introducing the func (n *NullInt64) Value() method because it was mentioned in the documentation. But I think I misunderstood something. Can anyone tell me what I did wrong?

Upvotes: 1

Views: 1610

Answers (1)

ifnotak
ifnotak

Reputation: 4662

UPDATE

There is an Example specifically for that. You may check it out. My other proposed solution should still work though.


Since the value you are trying to validate is Int64 inside sql.NullInt64, the easiest way would be to remove the validate tag and just register a Struct Level validation using:

validate.RegisterStructValidation(NullInt64StructLevelValidation, NullInt64{})

while NullInt64StructLevelValidation is a StructLevelFunc that looks like this:

func NullInt64StructLevelValidation(sl validator.StructLevel) {
    ni := sl.Current().Interface().(NullInt64)
    if ni.NullInt64.Int64 < 10 {
        sl.ReportError(ni.NullInt64.Int64, "Int64", "", "min", "")
    }
}

Note #1: this line thing := Thing{number,&number,n,&n} has one argument too many. I assume you meant thing := Thing{number, n, &n}

Note #2: Go tooling including gofmt is considered to be one of the most powerful features of the language. Please consider using it/them.

EDIT #1: I don't think implementing Valuer interface is of any value in this context.

Upvotes: 1

Related Questions