diff --git a/array.go b/array.go index 10bc094..dda42c2 100644 --- a/array.go +++ b/array.go @@ -5,6 +5,7 @@ import ( "github.com/pkg/errors" ) +// ArrayField is the type for validating arrays in a JSON type ArrayField struct { name string required bool @@ -20,17 +21,18 @@ type ArrayField struct { // To Force Implementing Field interface by ArrayField var _ Field = (*ArrayField)(nil) +// GetName returns name of the field func (a *ArrayField) GetName() string { return a.name } +// Validate is used for validating a value. it returns an error if the value is invalid. func (a *ArrayField) Validate(v interface{}) error { if v == nil { if !a.required { return nil - } else { - return errors.Errorf("Value for %s field is required", a.name) } + return errors.Errorf("Value for %s field is required", a.name) } values, ok := v.([]interface{}) @@ -60,23 +62,27 @@ func (a *ArrayField) Validate(v interface{}) error { return result } +// Required is called to make a field required in a JSON func (a *ArrayField) Required() *ArrayField { a.required = true return a } +// MinLength is called to set minimum length for an array field in a JSON func (a *ArrayField) MinLength(length int) *ArrayField { a.minLength = length a.minLengthValidation = true return a } +// MaxLength is called to set maximum length for an array field in a JSON func (a *ArrayField) MaxLength(length int) *ArrayField { a.maxLength = length a.maxLengthValidation = true return a } +// Array is the constructor of an array field. func Array(name string, itemField Field) *ArrayField { return &ArrayField{ name: name, diff --git a/array_spec.go b/array_spec.go index 8dd3916..dd75670 100644 --- a/array_spec.go +++ b/array_spec.go @@ -1,5 +1,6 @@ package vjson +// ArrayFieldSpec is a type used for parsing an ArrayField type ArrayFieldSpec struct { Name string `mapstructure:"name"` Required bool `mapstructure:"required"` @@ -8,6 +9,7 @@ type ArrayFieldSpec struct { MaxLength int `mapstructure:"max_length"` } +// NewArray receives an ArrayFieldSpec and returns and ArrayField func NewArray(spec ArrayFieldSpec, itemField Field, minLengthValidation, maxLengthValidation bool) *ArrayField { return &ArrayField{ name: spec.Name, diff --git a/boolean.go b/boolean.go index 654a7e1..fff5a48 100644 --- a/boolean.go +++ b/boolean.go @@ -2,6 +2,7 @@ package vjson import "github.com/pkg/errors" +// BooleanField is the type for validating booleans in a JSON type BooleanField struct { name string required bool @@ -12,17 +13,18 @@ type BooleanField struct { // To Force Implementing Field interface by BooleanField var _ Field = (*BooleanField)(nil) +// GetName returns name of the field func (b *BooleanField) GetName() string { return b.name } +// Validate is used for validating a value. it returns an error if the value is invalid. func (b *BooleanField) Validate(v interface{}) error { if v == nil { if !b.required { return nil - } else { - return errors.Errorf("Value for %s field is required", b.name) } + return errors.Errorf("Value for %s field is required", b.name) } value, ok := v.(bool) @@ -40,17 +42,20 @@ func (b *BooleanField) Validate(v interface{}) error { return nil } +// Required is called to make a field required in a JSON func (b *BooleanField) Required() *BooleanField { b.required = true return b } +// ShouldBe is called for setting a value for checking a boolean. func (b *BooleanField) ShouldBe(value bool) *BooleanField { b.value = value b.valueValidation = true return b } +// Boolean is the constructor of a boolean field func Boolean(name string) *BooleanField { return &BooleanField{ name: name, diff --git a/boolean_spec.go b/boolean_spec.go index a1fca36..5e22845 100644 --- a/boolean_spec.go +++ b/boolean_spec.go @@ -1,11 +1,13 @@ package vjson +// BooleanFieldSpec is a type used for parsing an BooleanField type BooleanFieldSpec struct { Name string `mapstructure:"name"` Required bool `mapstructure:"required"` Value bool `mapstructure:"value"` } +// NewBoolean receives an BooleanFieldSpec and returns and BooleanField func NewBoolean(spec BooleanFieldSpec, valueValidation bool) *BooleanField { return &BooleanField{ name: spec.Name, diff --git a/field.go b/field.go index 80e79d3..09f9a48 100644 --- a/field.go +++ b/field.go @@ -1,5 +1,7 @@ package vjson +// Field is the abstraction on a field in a json. +// different field types can be implemented with implementing this interface. type Field interface { GetName() string Validate(interface{}) error diff --git a/float.go b/float.go index 469bb7f..0aad5b1 100644 --- a/float.go +++ b/float.go @@ -12,6 +12,7 @@ type floatRange struct { end float64 } +// FloatField is the type for validating floats in a JSON type FloatField struct { name string required bool @@ -32,17 +33,18 @@ type FloatField struct { // To Force Implementing Field interface by IntegerField var _ Field = (*FloatField)(nil) +// GetName returns name of the field func (f *FloatField) GetName() string { return f.name } +// Validate is used for validating a value. it returns an error if the value is invalid. func (f *FloatField) Validate(v interface{}) error { if v == nil { if !f.required { return nil - } else { - return errors.Errorf("Value for %s field is required", f.name) } + return errors.Errorf("Value for %s field is required", f.name) } value, ok := v.(float64) @@ -95,41 +97,48 @@ func (f *FloatField) Validate(v interface{}) error { return result } +// Required is called to make a field required in a JSON func (f *FloatField) Required() *FloatField { f.required = true return f } +// Positive is called when we want to force the value to be positive in validation. func (f *FloatField) Positive() *FloatField { f.signValidation = true f.positive = true return f } +// Negative is called when we want to force the value to be negative in validation. func (f *FloatField) Negative() *FloatField { f.signValidation = true f.positive = false return f } +// Min is called when we want to set a minimum value for a float value in validation. func (f *FloatField) Min(value float64) *FloatField { f.min = value f.minValidation = true return f } +// Max is called when we want to set a maximum value for a float value in validation. func (f *FloatField) Max(value float64) *FloatField { f.max = value f.maxValidation = true return f } +// Range is called when we want to define valid ranges for a float value in validation. func (f *FloatField) Range(start, end float64) *FloatField { f.ranges = append(f.ranges, floatRange{start: start, end: end}) f.rangeValidation = true return f } +// Float is the constructor of a float field func Float(name string) *FloatField { return &FloatField{ name: name, diff --git a/float_spec.go b/float_spec.go index 0875328..1ee8e10 100644 --- a/float_spec.go +++ b/float_spec.go @@ -1,10 +1,12 @@ package vjson +// FloatRangeSpec is a type for parsing a float field range type FloatRangeSpec struct { Start float64 `mapstructure:"start"` End float64 `mapstructure:"end"` } +// FloatFieldSpec is a type used for parsing an FloatField type FloatFieldSpec struct { Name string `mapstructure:"name"` Required bool `mapstructure:"required"` @@ -14,6 +16,7 @@ type FloatFieldSpec struct { Ranges []FloatRangeSpec `mapstructure:"ranges"` } +// NewFloat receives an FloatFieldSpec and returns and FloatField func NewFloat(spec FloatFieldSpec, minValidation, maxValidation, signValidation, rangeValidation bool) *FloatField { ranges := make([]floatRange, 0, len(spec.Ranges)) for _, rangeSpec := range spec.Ranges { diff --git a/go.mod b/go.mod index 76c03c2..fbaf3eb 100644 --- a/go.mod +++ b/go.mod @@ -8,4 +8,6 @@ require ( github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.7.0 github.com/tidwall/gjson v1.7.5 + golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect + golang.org/x/tools v0.1.4 // indirect ) diff --git a/go.sum b/go.sum index df190b5..2b9ece2 100644 --- a/go.sum +++ b/go.sum @@ -19,6 +19,35 @@ github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE= github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.1.0 h1:K3hMW5epkdAVwibsQEfR/7Zj0Qgt4DxtNumTq/VloO8= github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7 h1:EBZoQjiKKPaLbPrbpssUfuHtwM6KV/vb4U85g/cigFY= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.1.4 h1:cVngSRcfgyZCzys3KYOpCFa+4dqX/Oub9tAq00ttGVs= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= diff --git a/integer.go b/integer.go index 1a590be..261a634 100644 --- a/integer.go +++ b/integer.go @@ -12,6 +12,7 @@ type intRange struct { end int } +// IntegerField is the type for validating integers in a JSON type IntegerField struct { name string required bool @@ -32,17 +33,18 @@ type IntegerField struct { // To Force Implementing Field interface by IntegerField var _ Field = (*IntegerField)(nil) +// GetName returns name of the field func (i *IntegerField) GetName() string { return i.name } +// Validate is used for validating a value. it returns an error if the value is invalid. func (i *IntegerField) Validate(v interface{}) error { if v == nil { if !i.required { return nil - } else { - return errors.Errorf("Value for %s field is required", i.name) } + return errors.Errorf("Value for %s field is required", i.name) } var value int var intOK bool @@ -104,41 +106,48 @@ func (i *IntegerField) Validate(v interface{}) error { return result } +// Required is called to make a field required in a JSON func (i *IntegerField) Required() *IntegerField { i.required = true return i } +// Positive is called when we want to force the value to be positive in validation. func (i *IntegerField) Positive() *IntegerField { i.signValidation = true i.positive = true return i } +// Negative is called when we want to force the value to be negative in validation. func (i *IntegerField) Negative() *IntegerField { i.signValidation = true i.positive = false return i } +// Min is called when we want to set a minimum value for an integer value in validation. func (i *IntegerField) Min(value int) *IntegerField { i.min = value i.minValidation = true return i } +// Max is called when we want to set a maximum value for an integer value in validation. func (i *IntegerField) Max(value int) *IntegerField { i.max = value i.maxValidation = true return i } +// Range is called when we want to define valid ranges for an integer value in validation. func (i *IntegerField) Range(start, end int) *IntegerField { i.ranges = append(i.ranges, intRange{start: start, end: end}) i.rangeValidation = true return i } +// Integer is the constructor of an integer field func Integer(name string) *IntegerField { return &IntegerField{ name: name, diff --git a/integer_spec.go b/integer_spec.go index bffad5e..4d86743 100644 --- a/integer_spec.go +++ b/integer_spec.go @@ -1,10 +1,12 @@ package vjson +// IntRangeSpec is a type for parsing an integer field range type IntRangeSpec struct { Start int `mapstructure:"start"` End int `mapstructure:"end"` } +// IntegerFieldSpec is a type used for parsing an IntegerField type IntegerFieldSpec struct { Name string `mapstructure:"name"` Required bool `mapstructure:"required"` @@ -14,6 +16,7 @@ type IntegerFieldSpec struct { Ranges []IntRangeSpec `mapstructure:"ranges"` } +// NewInteger receives an IntegerFieldSpec and returns and IntegerField func NewInteger(spec IntegerFieldSpec, minValidation, maxValidation, signValidation, rangeValidation bool) *IntegerField { ranges := make([]intRange, 0, len(spec.Ranges)) for _, rangeSpec := range spec.Ranges { diff --git a/null.go b/null.go index 394ff27..cca84a3 100644 --- a/null.go +++ b/null.go @@ -2,6 +2,7 @@ package vjson import "github.com/pkg/errors" +// NullField is the type for validating floats in a JSON type NullField struct { name string } @@ -9,10 +10,12 @@ type NullField struct { // To Force Implementing Field interface by NullField var _ Field = (*NullField)(nil) +// GetName returns name of the field func (n *NullField) GetName() string { return n.name } +// Validate is used for validating a value. it returns an error if the value is invalid. func (n *NullField) Validate(input interface{}) error { if input == nil { return nil @@ -20,6 +23,7 @@ func (n *NullField) Validate(input interface{}) error { return errors.Errorf("Value for %s should be null", n.name) } +// Null is the constructor of a null field in a JSON. func Null(name string) *NullField { return &NullField{ name: name, diff --git a/null_spec.go b/null_spec.go index 03c34ec..ac6dbe7 100644 --- a/null_spec.go +++ b/null_spec.go @@ -1,9 +1,11 @@ package vjson +// NullFieldSpec is a type used for parsing an NullField type NullFieldSpec struct { Name string `mapstructure:"name"` } +// NewNull receives an NullFieldSpec and returns and NullField func NewNull(spec NullFieldSpec) *NullField { return &NullField{ name: spec.Name, diff --git a/object.go b/object.go index 91b0366..86683a1 100644 --- a/object.go +++ b/object.go @@ -5,6 +5,7 @@ import ( "github.com/pkg/errors" ) +// ObjectField is the type for validating another JSON object in a JSON type ObjectField struct { name string required bool @@ -14,17 +15,18 @@ type ObjectField struct { // To Force Implementing Field interface by ObjectField var _ Field = (*ObjectField)(nil) +// GetName returns name of the field func (o *ObjectField) GetName() string { return o.name } +// Validate is used for validating a value. it returns an error if the value is invalid. func (o *ObjectField) Validate(v interface{}) error { if v == nil { if !o.required { return nil - } else { - return errors.Errorf("Value for %s field is required", o.name) } + return errors.Errorf("Value for %s field is required", o.name) } // The input is either string or an interface{} object @@ -44,11 +46,13 @@ func (o *ObjectField) Validate(v interface{}) error { return o.schema.ValidateBytes(jsonBytes) } +// Required is called to make a field required in a JSON func (o *ObjectField) Required() *ObjectField { o.required = true return o } +// Object is the constructor of an object field func Object(name string, schema Schema) *ObjectField { return &ObjectField{ name: name, diff --git a/object_spec.go b/object_spec.go index f4d848e..afdb352 100644 --- a/object_spec.go +++ b/object_spec.go @@ -1,11 +1,13 @@ package vjson +// ObjectFieldSpec is a type used for parsing an ObjectField type ObjectFieldSpec struct { Name string `mapstructure:"name"` Required bool `mapstructure:"required"` Schema map[string]interface{} `mapstructure:"schema"` } +// NewObject receives an ObjectFieldSpec and returns and ObjectField func NewObject(spec ObjectFieldSpec, schema Schema) *ObjectField { return &ObjectField{ name: spec.Name, diff --git a/schema.go b/schema.go index e1ed8e1..5bcfbd3 100644 --- a/schema.go +++ b/schema.go @@ -10,14 +10,17 @@ import ( "os" ) +// Schema is the type for declaring a JSON schema and validating a json object. type Schema struct { Fields []Field } +// SchemaSpec is used for parsing a Schema type SchemaSpec struct { Fields []map[string]interface{} `json:"fields"` } +// UnmarshalJSON is implemented for parsing a Schema. it overrides json.Unmarshal behaviour. func (s *Schema) UnmarshalJSON(bytes []byte) error { var schemaSpec SchemaSpec err := json.Unmarshal(bytes, &schemaSpec) @@ -41,13 +44,13 @@ func (s *Schema) UnmarshalJSON(bytes []byte) error { } func (s *Schema) getField(fieldSpec map[string]interface{}) (Field, error) { - fieldTypeRaw, found := fieldSpec[TypeKey] + fieldTypeRaw, found := fieldSpec[typeKey] if found { fieldTypeStr, ok := fieldTypeRaw.(string) if ok { - fieldType := FieldType(fieldTypeStr) + fieldType := fieldType(fieldTypeStr) switch fieldType { - case IntegerType: + case integerType: { field, err := s.getIntegerField(fieldSpec) if err != nil { @@ -55,7 +58,7 @@ func (s *Schema) getField(fieldSpec map[string]interface{}) (Field, error) { } return field, nil } - case FloatType: + case floatType: { field, err := s.getFloatField(fieldSpec) if err != nil { @@ -63,7 +66,7 @@ func (s *Schema) getField(fieldSpec map[string]interface{}) (Field, error) { } return field, nil } - case StringType: + case stringType: { field, err := s.getStringField(fieldSpec) if err != nil { @@ -71,7 +74,7 @@ func (s *Schema) getField(fieldSpec map[string]interface{}) (Field, error) { } return field, nil } - case ArrayType: + case arrayType: { field, err := s.getArrayField(fieldSpec) if err != nil { @@ -79,7 +82,7 @@ func (s *Schema) getField(fieldSpec map[string]interface{}) (Field, error) { } return field, nil } - case BooleanType: + case booleanType: { field, err := s.getBooleanField(fieldSpec) if err != nil { @@ -87,7 +90,7 @@ func (s *Schema) getField(fieldSpec map[string]interface{}) (Field, error) { } return field, nil } - case ObjectType: + case objectType: { field, err := s.getObjectField(fieldSpec) if err != nil { @@ -95,7 +98,7 @@ func (s *Schema) getField(fieldSpec map[string]interface{}) (Field, error) { } return field, nil } - case NullType: + case nullType: { field, err := s.getNullField(fieldSpec) if err != nil { @@ -268,6 +271,9 @@ func (s *Schema) getNullField(fieldSpec map[string]interface{}) (*NullField, err return nullField, nil } + +// ValidateBytes receives a byte array of a json object and validates it according to the specified Schema. +// it returns an error if the input is invalid. func (s *Schema) ValidateBytes(input []byte) error { if gjson.ValidBytes(input) { jsonObject := gjson.ParseBytes(input) @@ -276,6 +282,7 @@ func (s *Schema) ValidateBytes(input []byte) error { return errors.Errorf("could not parse json input.") } +// ValidateString is like ValidateBytes but it receives the json object as string input. func (s *Schema) ValidateString(input string) error { if gjson.Valid(input) { jsonObject := gjson.Parse(input) @@ -297,14 +304,17 @@ func (s *Schema) validateJSON(json gjson.Result) error { return result } +// NewSchema is the constructor for Schema. it receives a list of Field in its arguments. func NewSchema(fields ...Field) Schema { return Schema{Fields: fields} } +// ReadFromString is for parsing a Schema from a string input. func ReadFromString(input string) (*Schema, error) { return ReadFromBytes([]byte(input)) } +// ReadFromBytes is for parsing a Schema from a byte array input. func ReadFromBytes(input []byte) (*Schema, error) { var s Schema err := json.Unmarshal(input, &s) @@ -314,6 +324,7 @@ func ReadFromBytes(input []byte) (*Schema, error) { return &s, nil } +// ReadFromFile is for parsing a Schema from a file input. func ReadFromFile(filePath string) (*Schema, error) { file, err := os.Open(filePath) if err != nil { diff --git a/string.go b/string.go index 42a5200..40ff123 100644 --- a/string.go +++ b/string.go @@ -7,6 +7,7 @@ import ( "strings" ) +// StringField is the type for validating strings in a JSON type StringField struct { name string required bool @@ -27,15 +28,18 @@ type StringField struct { // To Force Implementing Field interface by StringField var _ Field = (*StringField)(nil) +// GetName returns name of the field func (s *StringField) GetName() string { return s.name } +// Required is called to make a field required in a JSON func (s *StringField) Required() *StringField { s.required = true return s } +// MinLength is called to set a minimum length to a string field func (s *StringField) MinLength(length int) *StringField { if length < 0 { return s @@ -45,6 +49,7 @@ func (s *StringField) MinLength(length int) *StringField { return s } +// MaxLength is called to set a maximum length to a string field func (s *StringField) MaxLength(length int) *StringField { if length < 0 { return s @@ -54,25 +59,27 @@ func (s *StringField) MaxLength(length int) *StringField { return s } +// Format is called to set a regex format for validation of a string field func (s *StringField) Format(format string) *StringField { s.format = format s.validateFormat = true return s } +// Choices is called to set valid choices of a string field in validation func (s *StringField) Choices(choices ...string) *StringField { s.choices = choices s.validateChoices = true return s } +// Validate is used for validating a value. it returns an error if the value is invalid. func (s *StringField) Validate(value interface{}) error { if value == nil { if !s.required { return nil - } else { - return errors.Errorf("Value for %s field is required", s.name) } + return errors.Errorf("Value for %s field is required", s.name) } stringValue, ok := value.(string) @@ -121,6 +128,7 @@ func (s *StringField) Validate(value interface{}) error { return result } +// String is the constructor of a string field func String(name string) *StringField { return &StringField{ name: name, diff --git a/string_spec.go b/string_spec.go index 70494a5..79631ad 100644 --- a/string_spec.go +++ b/string_spec.go @@ -1,5 +1,6 @@ package vjson +// StringFieldSpec is a type used for parsing an StringField type StringFieldSpec struct { Name string `mapstructure:"name"` Required bool `mapstructure:"required"` @@ -9,6 +10,7 @@ type StringFieldSpec struct { Choices []string `mapstructure:"choices"` } +// NewString receives an StringFieldSpec and returns and StringField func NewString(spec StringFieldSpec, minLengthValidation, maxLengthValidation, formatValidation, choiceValidation bool) *StringField { return &StringField{ name: spec.Name, diff --git a/types.go b/types.go index 2ed7a07..cfae736 100644 --- a/types.go +++ b/types.go @@ -1,15 +1,15 @@ package vjson -type FieldType string +type fieldType string const ( - IntegerType FieldType = "integer" - FloatType FieldType = "float" - StringType FieldType = "string" - ArrayType FieldType = "array" - BooleanType FieldType = "boolean" - ObjectType FieldType = "object" - NullType FieldType = "null" + integerType fieldType = "integer" + floatType fieldType = "float" + stringType fieldType = "string" + arrayType fieldType = "array" + booleanType fieldType = "boolean" + objectType fieldType = "object" + nullType fieldType = "null" ) -const TypeKey = "type" +const typeKey = "type"