vjson

package module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 18, 2022 License: MIT Imports: 10 Imported by: 2

README

vjson

codecov Go Report Card Go Reference

vjson is a Go package that helps to validate JSON objects in a declarative way.

Getting Started

Installing

For installing vjson, use command below:

go get -u github.com/miladibra10/vjson

Concepts

There are two main concepts in vjson that are:

  • Schema
  • Field

Schema

A schema is the holder of JSON object specifications. It contains the way of validation of a JSON object. a schema consists of an array of fields.

Field

A field contains characteristics of a specific field of a json object. multiple field types are supported by vjson. list of supported types are:

  • integer
  • float
  • string
  • boolean
  • array
  • object
  • null

How to create a Schema

There are two ways to create a schema.

  • Schema could be declared in code in a declarative manner.
  • Schema could be parsed from a file or string.

Schema in code

Schema could be declared in code like this:

package main

import "github.com/miladibra10/vjson"

func main() {
	schema := vjson.NewSchema(
		vjson.String("name").Required(),
	)

	jsonString := `
	{
		"name": "James"
	}
	`

	err := schema.ValidateString(jsonString)
	if err != nil {
		panic(err)
	}
}

schema object contains a string field, named name. This code validates jsonString.

Parse Schema

Schema could be parsed from a file or a string. These methods help to parse schema.

Format of schema for parsing should be a json like this:

{
  "fields": [
    ...
  ]
}

fields should contain field specifications.

This code parses a schema from string:

package main

import "github.com/miladibra10/vjson"

func main() {
	schemaStr := `
	{
		"fields": [
			{
				"name": "name",
				"type": "string"
				"required": true
			}
		]
	}
	`
	schema, err := vjson.ReadFromString(schemaStr)
	if err != nil {
		panic(err)
	}

	jsonString := `
	{
		"name": "James"
	}
	`

	err = schema.ValidateString(jsonString)
	if err != nil {
		panic(err)
	}
}

schemaStr describes the schema and vjson.ReadFromString(schemaStr) parses the string and returns a schema object.

schema object contains a string field, named name. This code validates jsonString.

Note: You could Marshal your schema as a json object for backup usages with json.Marshal function.

Fields

Integer

An integer field could be created in code like this:

vjson.Integer("foo")

some validation characteristics could be added to an integer field with chaining some functions:

  • Required() sets the field as a required field. validation will return an error if a required field is not present in json object.
  • Min(min int) forces the integer field to be greater than min in validating json object.
  • Max(max int) forces the integer field to be lower than max in validating json object.
  • Positive() checks if the value of field is positive.
  • Negative() checks if the value of field is negative.
  • Range(start, end int) adds a range for integer field. the value of json field should be within this range.

integer field could be described by a json for schema parsing.

  • name: the name of the field
  • type: type value for integer field must be integer
  • required: whether the field is required or not
  • min: minimum value of field
  • max: maximum value of field
  • positive: a boolean that describes that a field is positive or negative (true for positive and false for negative)
  • ranges: an array of ranges to be checked in field validation.
Example

an integer field, named foo which is required, minimum value should be 2, maximum value should be 10, should be positive and be within range [3,5] or [6,8] ,could be declared like this:

Code
vjson.Integer("foo").Required().Min(2).Max(10).Positive().Range(3,5).Range(6,8)
File
{
  "name": "foo",
  "type": "integer",
  "required": true,
  "min": 2,
  "max": 10,
  "positive": true,
  "ranges": [
    {
      "start": 3,
      "end": 5
    },
    {
      "start": 6,
      "end": 8
    }
  ]
}

Float

A float field could be created in code like this:

vjson.Float("foo")

some validation characteristics could be added to a float field with chaining some functions:

  • Required() sets the field as a required field. validation will return an error if a required field is not present in json object.
  • Min(min float64) forces the float field to be greater than min in validating json object.
  • Max(max float64) forces the float field to be lower than max in validating json object.
  • Positive() checks if the value of field is positive.
  • Negative() checks if the value of field is negative.
  • Range(start, end float64) adds a range for float field. the value of json field should be within this range.

float field could be described by a json for schema parsing.

  • name: the name of the field
  • type: type value for float field must be float
  • required: whether the field is required or not
  • min: minimum value of field
  • max: maximum value of field
  • positive: a boolean that describes that a field is positive or negative (true for positive and false for negative)
  • ranges: an array of ranges to be checked in field validation.
Example

a float field, named foo which is required, minimum value should be 2.5, maximum value should be 10.5, should be positive and be within range [3,5] or [6,8] ,could be declared like this:

Code
vjson.Float("foo").Required().Min(2.5).Max(10.5).Positive().Range(3,5).Range(6,8)
File
{
  "name": "foo",
  "type": "float",
  "required": true,
  "min": 2.5,
  "max": 10.5,
  "positive": true,
  "ranges": [
    {
      "start": 3,
      "end": 5
    },
    {
      "start": 6,
      "end": 8
    }
  ]
}

String

A string field could be created in code like this:

vjson.String("foo")

some validation characteristics could be added to a string field with chaining some functions:

  • Required() sets the field as a required field. validation will return an error if a required field is not present in json object.
  • MinLength(min int) forces the length of string field to be greater than min in validating json object.
  • MaxLength(max int) forces the length of string field to be lower than max in validating json object.
  • Format(format string) gets a regex format and checks if value of json object matches the format.
  • Choices(choice ...string) checks if the value of string field is equal to one of choices.

float field could be described by a json for schema parsing.

  • name: the name of the field
  • type: type value for string field must be string
  • required: whether the field is required or not
  • min_length: minimum length of string value of field
  • max_length: maximum length of string value of field
  • format: a regex format and checks if value of json object matches the format.
  • choices: a list of strings that value of field should be equal to one of them.
Example

a string field, named foo which is required, minimum length value should be 2, maximum length value should be 10, should be Equal to one of these values: first, second could be declared like this:

Code
vjson.String("foo").Required().MinLength(2).MaxLength(10).Choices("first", "second")
File
{
  "name": "foo",
  "type": "string",
  "required": true,
  "min_length": 2,
  "max_length": 10,
  "choices": [
    "first",
    "second"
  ]
}

Boolean

A boolean field could be created in code like this:

vjson.Boolean("foo")

some validation characteristics could be added to a boolean field with chaining some functions:

  • Required() sets the field as a required field. validation will return an error if a required field is not present in json object.
  • ShouldBe(value bool) forces the value of field be equal to value

boolean field could be described by a json for schema parsing.

  • name: the name of the field
  • type: type value for boolean field must be boolean
  • required: whether the field is required or not
  • value: a boolean (same sa ShouldBe in code) that describes that the value of json field.
Example

a boolean field, named foo which is required, and always should be false, could be declared like this:

Code
vjson.Boolean("foo").Required().ShouldBe(false)
File
{
  "name": "foo",
  "type": "boolean",
  "required": true,
  "value": false
}

Array

An array field could be created in code like this:

vjson.Array("foo", vjson.String("item"))

the first argument is the name of array field, and the second one is the field characteristics of each item of array.

some validation characteristics could be added to an array field with chaining some functions:

  • Required() sets the field as a required field. validation will return an error if a required field is not present in json object.
  • MinLength(min int) forces the length of array field to be greater than min in validating json object.
  • MaxLength(max int) forces the length of array field to be lower than max in validating json object.

array field could be described by a json for schema parsing.

  • name: the name of the field
  • type: type value for array field must be array
  • required: whether the field is required or not
  • min_length: minimum length of array
  • max_length: maximum length of array
  • items: specifications of item fields. could be any field.
Example

an array field, named foo with integer items between [0,20] range, which is required, and its length should be at least 2 and at last 10, could be declared like this:

Code
vjson.Array("foo", vjson.Integer("item").Range(0,20)).Required().MinLength(2).MaxLength(10)
File
{
  "name": "foo",
  "type": "array",
  "required": true,
  "min_length": 2,
  "max_length": 10,
  "items": {
    "name": "item",
    "type": "integer",
    "ranges": [
      {
        "start": 0,
        "end": 20
      }
    ]
  }
}

Object

An object field could be created in code like this:

vjson.Object("foo", vjson.NewSchema(
        /// Fields	
	))

the first argument is the name of object field, and the second one is the schema of object value. this feature helps validation of nested json objects

some validation characteristics could be added to an array field with chaining some functions:

  • Required() sets the field as a required field. validation will return an error if a required field is not present in json object.

object field could be described by a json for schema parsing.

  • name: the name of the field
  • type: type value for object field must be object
  • required: whether the field is required or not
  • schema: schema of object value.
Example

a required object field, named foo which its valid value is an object with name and last_name required strings, could be declared like this:

Code
vjson.Object("foo", vjson.NewSchema(
	vjson.String("name").Required(),
	vjson.String("last_name").Required(),
	)).Required()
File
{
  "name": "foo",
  "type": "object",
  "required": true,
  "schema": {
    "fields": [
      {
        "name": "name",
        "type": "string",
        "required": true
      },
      {
        "name": "last_name",
        "type": "string",
        "required": true
      }
    ]
  }
}

Null

A null field (a field that its value should be null!) could be created in code like this:

vjson.Null("foo")

null field could be described by a json for schema parsing.

  • name: the name of the field
  • type: type value for null field must be null
Example

a null field, named foo, could be declared like this:

Code
vjson.Null("foo")
File
{
  "name": "foo",
  "type": "null"
}

Validation

After creating a schema, you can validate your json objects with these methods:

  • ValidateBytes(input []byte): receives a byte array as a json input and validates it. this method returns an error. it would be nil if the object is valid, and it will return an error if the input object is not valid.
  • ValidateString(input string): acts like ValidateBytes but its argument is string.

Example

This code validates an object that should have name and age fields.

package main

import "github.com/miladibra10/vjson"

func main() {
	schema := vjson.NewSchema(
		vjson.String("name").Required(),
		vjson.Integer("age").Positive(),
	)

	jsonString := `
	{
		
  "required": true,
  "value": false"name": "James"
	}
	`

	err := schema.ValidateString(jsonString)
	if err != nil {
		panic(err) // Will not panic
	}

	jsonString = `
	{
		"name": "James",
        "age": 10
	}
	`

	err = schema.ValidateString(jsonString)
	if err != nil {
		panic(err) // Will not panic
	}

	jsonString = `
	{
        "age": 10
	}
	`

	err = schema.ValidateString(jsonString)
	if err != nil {
		panic(err) // Will panic because name field is missing in jsonString
	}
	
}

Benchmarks

Results of benchmarking validation functions highly depends on types and number of fields.

two simple benchmarks (exists in schema_test.go file) with using all features of vjson gives this result:

goos: linux
goarch: amd64
pkg: github.com/miladibra10/vjson
BenchmarkSchema_ValidateString-8          416664              2792 ns/op
BenchmarkSchema_ValidateBytes-8           431734              2858 ns/op
PASS
ok      github.com/miladibra10/vjson    2.461s

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ArrayField

type ArrayField struct {
	// contains filtered or unexported fields
}

ArrayField is the type for validating arrays in a JSON

func Array

func Array(name string, itemField Field) *ArrayField

Array is the constructor of an array field.

func NewArray

func NewArray(spec ArrayFieldSpec, itemField Field, minLengthValidation, maxLengthValidation bool) *ArrayField

NewArray receives an ArrayFieldSpec and returns and ArrayField

func (*ArrayField) GetName

func (a *ArrayField) GetName() string

GetName returns name of the field

func (*ArrayField) MarshalJSON added in v0.3.0

func (a *ArrayField) MarshalJSON() ([]byte, error)

func (*ArrayField) MaxLength

func (a *ArrayField) MaxLength(length int) *ArrayField

MaxLength is called to set maximum length for an array field in a JSON

func (*ArrayField) MinLength

func (a *ArrayField) MinLength(length int) *ArrayField

MinLength is called to set minimum length for an array field in a JSON

func (*ArrayField) Required

func (a *ArrayField) Required() *ArrayField

Required is called to make a field required in a JSON

func (*ArrayField) Validate

func (a *ArrayField) Validate(v interface{}) error

Validate is used for validating a value. it returns an error if the value is invalid.

type ArrayFieldSpec

type ArrayFieldSpec struct {
	Name      string                 `mapstructure:"name" json:"name"`
	Type      fieldType              `json:"type"`
	Required  bool                   `mapstructure:"required" json:"required,omitempty"`
	Items     map[string]interface{} `mapstructure:"items" json:"items,omitempty"`
	MinLength int                    `mapstructure:"min_length" json:"minLength,omitempty"`
	MaxLength int                    `mapstructure:"max_length" json:"maxLength,omitempty"`
}

ArrayFieldSpec is a type used for parsing an ArrayField

type BooleanField

type BooleanField struct {
	// contains filtered or unexported fields
}

BooleanField is the type for validating booleans in a JSON

func Boolean

func Boolean(name string) *BooleanField

Boolean is the constructor of a boolean field

func NewBoolean

func NewBoolean(spec BooleanFieldSpec, valueValidation bool) *BooleanField

NewBoolean receives an BooleanFieldSpec and returns and BooleanField

func (*BooleanField) GetName

func (b *BooleanField) GetName() string

GetName returns name of the field

func (*BooleanField) MarshalJSON added in v0.3.0

func (b *BooleanField) MarshalJSON() ([]byte, error)

func (*BooleanField) Required

func (b *BooleanField) Required() *BooleanField

Required is called to make a field required in a JSON

func (*BooleanField) ShouldBe

func (b *BooleanField) ShouldBe(value bool) *BooleanField

ShouldBe is called for setting a value for checking a boolean.

func (*BooleanField) Validate

func (b *BooleanField) Validate(v interface{}) error

Validate is used for validating a value. it returns an error if the value is invalid.

type BooleanFieldSpec

type BooleanFieldSpec struct {
	Name     string    `mapstructure:"name" json:"name"`
	Type     fieldType `json:"type"`
	Required bool      `mapstructure:"required" json:"required,omitempty"`
	Value    bool      `mapstructure:"value" json:"value,omitempty"`
}

BooleanFieldSpec is a type used for parsing an BooleanField

type Field

type Field interface {
	json.Marshaler
	GetName() string
	Validate(interface{}) error
}

Field is the abstraction on a field in a json. different field types can be implemented with implementing this interface.

type FloatField

type FloatField struct {
	// contains filtered or unexported fields
}

FloatField is the type for validating floats in a JSON

func Float

func Float(name string) *FloatField

Float is the constructor of a float field

func NewFloat

func NewFloat(spec FloatFieldSpec, minValidation, maxValidation, signValidation, rangeValidation bool) *FloatField

NewFloat receives an FloatFieldSpec and returns and FloatField

func (*FloatField) GetName

func (f *FloatField) GetName() string

GetName returns name of the field

func (*FloatField) MarshalJSON added in v0.3.0

func (f *FloatField) MarshalJSON() ([]byte, error)

func (*FloatField) Max

func (f *FloatField) Max(value float64) *FloatField

Max is called when we want to set a maximum value for a float value in validation.

func (*FloatField) Min

func (f *FloatField) Min(value float64) *FloatField

Min is called when we want to set a minimum value for a float value in validation.

func (*FloatField) Negative

func (f *FloatField) Negative() *FloatField

Negative is called when we want to force the value to be negative in validation.

func (*FloatField) Positive

func (f *FloatField) Positive() *FloatField

Positive is called when we want to force the value to be positive in validation.

func (*FloatField) Range

func (f *FloatField) Range(start, end float64) *FloatField

Range is called when we want to define valid ranges for a float value in validation.

func (*FloatField) Required

func (f *FloatField) Required() *FloatField

Required is called to make a field required in a JSON

func (*FloatField) Validate

func (f *FloatField) Validate(v interface{}) error

Validate is used for validating a value. it returns an error if the value is invalid.

type FloatFieldSpec

type FloatFieldSpec struct {
	Name     string           `mapstructure:"name" json:"name"`
	Type     fieldType        `json:"type"`
	Required bool             `mapstructure:"required" json:"required,omitempty"`
	Min      float64          `mapstructure:"min" json:"min,omitempty"`
	Max      float64          `mapstructure:"max" json:"max,omitempty"`
	Positive bool             `mapstructure:"positive" json:"positive,omitempty"`
	Ranges   []FloatRangeSpec `mapstructure:"ranges" json:"ranges,omitempty"`
}

FloatFieldSpec is a type used for parsing an FloatField

type FloatRangeSpec

type FloatRangeSpec struct {
	Start float64 `mapstructure:"start" json:"start"`
	End   float64 `mapstructure:"end" json:"end"`
}

FloatRangeSpec is a type for parsing a float field range

type IntRangeSpec

type IntRangeSpec struct {
	Start int `mapstructure:"start" json:"start"`
	End   int `mapstructure:"end" json:"end"`
}

IntRangeSpec is a type for parsing an integer field range

type IntegerField

type IntegerField struct {
	// contains filtered or unexported fields
}

IntegerField is the type for validating integers in a JSON

func Integer

func Integer(name string) *IntegerField

Integer is the constructor of an integer field

func NewInteger

func NewInteger(spec IntegerFieldSpec, minValidation, maxValidation, signValidation, rangeValidation bool) *IntegerField

NewInteger receives an IntegerFieldSpec and returns and IntegerField

func (*IntegerField) GetName

func (i *IntegerField) GetName() string

GetName returns name of the field

func (*IntegerField) MarshalJSON added in v0.3.0

func (i *IntegerField) MarshalJSON() ([]byte, error)

func (*IntegerField) Max

func (i *IntegerField) Max(value int) *IntegerField

Max is called when we want to set a maximum value for an integer value in validation.

func (*IntegerField) Min

func (i *IntegerField) Min(value int) *IntegerField

Min is called when we want to set a minimum value for an integer value in validation.

func (*IntegerField) Negative

func (i *IntegerField) Negative() *IntegerField

Negative is called when we want to force the value to be negative in validation.

func (*IntegerField) Positive

func (i *IntegerField) Positive() *IntegerField

Positive is called when we want to force the value to be positive in validation.

func (*IntegerField) Range

func (i *IntegerField) Range(start, end int) *IntegerField

Range is called when we want to define valid ranges for an integer value in validation.

func (*IntegerField) Required

func (i *IntegerField) Required() *IntegerField

Required is called to make a field required in a JSON

func (*IntegerField) Validate

func (i *IntegerField) Validate(v interface{}) error

Validate is used for validating a value. it returns an error if the value is invalid.

type IntegerFieldSpec

type IntegerFieldSpec struct {
	Name     string         `mapstructure:"name" json:"name"`
	Type     fieldType      `json:"type"`
	Required bool           `mapstructure:"required" json:"required,omitempty"`
	Min      int            `mapstructure:"min" json:"min,omitempty"`
	Max      int            `mapstructure:"max" json:"max,omitempty"`
	Positive bool           `mapstructure:"positive" json:"positive,omitempty"`
	Ranges   []IntRangeSpec `mapstructure:"ranges" json:"ranges,omitempty"`
}

IntegerFieldSpec is a type used for parsing an IntegerField

type NullField

type NullField struct {
	// contains filtered or unexported fields
}

NullField is the type for validating floats in a JSON

func NewNull

func NewNull(spec NullFieldSpec) *NullField

NewNull receives an NullFieldSpec and returns and NullField

func Null

func Null(name string) *NullField

Null is the constructor of a null field in a JSON.

func (*NullField) GetName

func (n *NullField) GetName() string

GetName returns name of the field

func (*NullField) MarshalJSON added in v0.3.0

func (n *NullField) MarshalJSON() ([]byte, error)

func (*NullField) Validate

func (n *NullField) Validate(input interface{}) error

Validate is used for validating a value. it returns an error if the value is invalid.

type NullFieldSpec

type NullFieldSpec struct {
	Name string    `mapstructure:"name" json:"name"`
	Type fieldType `json:"type"`
}

NullFieldSpec is a type used for parsing an NullField

type ObjectField

type ObjectField struct {
	// contains filtered or unexported fields
}

ObjectField is the type for validating another JSON object in a JSON

func NewObject

func NewObject(spec ObjectFieldSpec, schema Schema) *ObjectField

NewObject receives an ObjectFieldSpec and returns and ObjectField

func Object

func Object(name string, schema Schema) *ObjectField

Object is the constructor of an object field

func (*ObjectField) GetName

func (o *ObjectField) GetName() string

GetName returns name of the field

func (*ObjectField) MarshalJSON added in v0.3.0

func (o *ObjectField) MarshalJSON() ([]byte, error)

func (*ObjectField) Required

func (o *ObjectField) Required() *ObjectField

Required is called to make a field required in a JSON

func (*ObjectField) Validate

func (o *ObjectField) Validate(v interface{}) error

Validate is used for validating a value. it returns an error if the value is invalid.

type ObjectFieldSpec

type ObjectFieldSpec struct {
	Name     string                 `mapstructure:"name" json:"name"`
	Type     fieldType              `json:"type"`
	Required bool                   `mapstructure:"required" json:"required,omitempty"`
	Schema   map[string]interface{} `mapstructure:"schema" json:"schema,omitempty"`
}

ObjectFieldSpec is a type used for parsing an ObjectField

type Schema

type Schema struct {
	Fields []Field `json:"fields"`
}

Schema is the type for declaring a JSON schema and validating a json object.

func NewSchema

func NewSchema(fields ...Field) Schema

NewSchema is the constructor for Schema. it receives a list of Field in its arguments.

func ReadFromBytes

func ReadFromBytes(input []byte) (*Schema, error)

ReadFromBytes is for parsing a Schema from a byte array input.

func ReadFromFile

func ReadFromFile(filePath string) (*Schema, error)

ReadFromFile is for parsing a Schema from a file input.

func ReadFromString

func ReadFromString(input string) (*Schema, error)

ReadFromString is for parsing a Schema from a string input.

func (*Schema) UnmarshalJSON

func (s *Schema) UnmarshalJSON(bytes []byte) error

UnmarshalJSON is implemented for parsing a Schema. it overrides json.Unmarshal behaviour.

func (*Schema) ValidateBytes

func (s *Schema) ValidateBytes(input []byte) error

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 (*Schema) ValidateString

func (s *Schema) ValidateString(input string) error

ValidateString is like ValidateBytes but it receives the json object as string input.

type SchemaSpec

type SchemaSpec struct {
	Fields []map[string]interface{} `json:"fields"`
}

SchemaSpec is used for parsing a Schema

type StringField

type StringField struct {
	// contains filtered or unexported fields
}

StringField is the type for validating strings in a JSON

func NewString

func NewString(spec StringFieldSpec, minLengthValidation, maxLengthValidation, formatValidation, choiceValidation bool) *StringField

NewString receives an StringFieldSpec and returns and StringField

func String

func String(name string) *StringField

String is the constructor of a string field

func (*StringField) Choices

func (s *StringField) Choices(choices ...string) *StringField

Choices function is called to set valid choices of a string field in validation

func (*StringField) Format

func (s *StringField) Format(format string) *StringField

Format is called to set a regex format for validation of a string field

func (*StringField) GetName

func (s *StringField) GetName() string

GetName returns name of the field

func (*StringField) MarshalJSON added in v0.3.0

func (s *StringField) MarshalJSON() ([]byte, error)

func (*StringField) MaxLength

func (s *StringField) MaxLength(length int) *StringField

MaxLength is called to set a maximum length to a string field

func (*StringField) MinLength

func (s *StringField) MinLength(length int) *StringField

MinLength is called to set a minimum length to a string field

func (*StringField) Required

func (s *StringField) Required() *StringField

Required is called to make a field required in a JSON

func (*StringField) Validate

func (s *StringField) Validate(value interface{}) error

Validate is used for validating a value. it returns an error if the value is invalid.

type StringFieldSpec

type StringFieldSpec struct {
	Name      string    `mapstructure:"name" json:"name"`
	Type      fieldType `json:"type"`
	Required  bool      `mapstructure:"required" json:"required,omitempty"`
	MinLength int       `mapstructure:"min_length" json:"minLength,omitempty"`
	MaxLength int       `mapstructure:"max_length" json:"maxLength,omitempty"`
	Format    string    `mapstructure:"format" json:"format,omitempty"`
	Choices   []string  `mapstructure:"choices" json:"choices,omitempty"`
}

StringFieldSpec is a type used for parsing an StringField

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL