jsonmap

package module
v0.0.0-...-389555d Latest Latest
Warning

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

Go to latest
Published: Feb 19, 2020 License: Apache-2.0 Imports: 13 Imported by: 1

README

Build Status Coverage Status

JSON validator and mapper

Validate JSON, and deserialize it into a structure without modifying or tagging the structure.

Example

package main

import "github.com/russellhaering/jsonmap"

type Dog struct {
	Name string
	Age  int
}

var DogTypeMap = jsonmap.StructMap{
	Dog{},
	[]jsonmap.MappedField{
		{
			StructFieldName: "Name",
			JSONFieldName:   "name",
			Validator:       jsonmap.String(1, 128),
		},
		{
			StructFieldName: "Age",
			JSONFieldName:   "age",
			Validator:       jsonmap.Integer(0, 1024),
		},
	},
}

var DemoTypeMapper = jsonmap.NewTypeMapper(
	DogTypeMap,
)

func main() {
	d := &Dog{}
	err := DemoTypeMapper.Unmarshal([]byte(`{"name": "Spot", "age": 4}`), d)
	if err != nil {
		panic(err)
	}
	println(d.Name)
	println(d.Age)
}

Why?

Use of struct tags to describe how to map JSON encourages bad design patterns. Developers end up putting JSON struct tags in places they have no business (like database objects, which should have no idea how some other layer might choose to serialize them) or writing tons of boiler plate to map API level structures to database objects. Using jsonmap is a way to avoid that boilerplate.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func StringRangeValidator

func StringRangeValidator(min, max int) func(string) bool

Some useful validators

func StringRegexValidator

func StringRegexValidator(r *regexp.Regexp) func(string) bool

func StringRenderer

func StringRenderer(text string) *stringRenderer

Types

type BoolQueryParameterMapper

type BoolQueryParameterMapper struct {
	// Returns true on nil slices and empty strings
	EmptyTrue bool
}

Probably doesn't need Validators

func (BoolQueryParameterMapper) Decode

func (bqpm BoolQueryParameterMapper) Decode(src ...string) (interface{}, error)

func (BoolQueryParameterMapper) Encode

func (bqpm BoolQueryParameterMapper) Encode(src reflect.Value) ([]string, error)

type BooleanValidator

type BooleanValidator struct{}

func (*BooleanValidator) Validate

func (v *BooleanValidator) Validate(value interface{}) (interface{}, error)

type Context

type Context interface{}
var EmptyContext Context

type Discriminator

type Discriminator struct {
	PropertyName string
	Mapping      map[string]TypeMap
}

The discrimator is used to handle cases in which a JSON property may be more than one type (e.g. Human.Pet may be type Dog or Cat). PropertyName is the name of said property and Mapping is a map between the possible types (as strings) and the appropriate TypeMap corresponding to the given type. See https://swagger.io/specification/#discriminatorObject for more information.

func (*Discriminator) Marshal

func (vt *Discriminator) Marshal(ctx Context, parent *reflect.Value, src reflect.Value) (json.Marshaler, error)

func (*Discriminator) Unmarshal

func (vt *Discriminator) Unmarshal(ctx Context, parent *reflect.Value, partial interface{}, dstValue reflect.Value) error

type EnumeratedValuesValidator

type EnumeratedValuesValidator struct {
	AllowedSlice  []string
	AllowedValues map[string]struct{}
}

func (*EnumeratedValuesValidator) Validate

func (v *EnumeratedValuesValidator) Validate(value interface{}) (interface{}, error)

type FlattenedPathError

type FlattenedPathError struct {
	Path    string
	Message string
}

func NewFlattenedPathError

func NewFlattenedPathError(path, message string) *FlattenedPathError

func (*FlattenedPathError) String

func (e *FlattenedPathError) String() string

type IntQueryParameterMapper

type IntQueryParameterMapper struct {
	Validators []func(int64) bool
	BitSize    int
}

func (IntQueryParameterMapper) Decode

func (iqpm IntQueryParameterMapper) Decode(src ...string) (interface{}, error)

func (IntQueryParameterMapper) Encode

func (iqpm IntQueryParameterMapper) Encode(src reflect.Value) ([]string, error)

type IntegerValidator

type IntegerValidator struct {
	MinVal int64
	MaxVal int64
}

TODO: The spectrum of numeric types deserves more thought. Do we ship independent validators for each?

func (*IntegerValidator) Validate

func (v *IntegerValidator) Validate(value interface{}) (interface{}, error)

type InterfaceValidator

type InterfaceValidator struct{}

func Interface

func Interface() *InterfaceValidator

func (*InterfaceValidator) Validate

func (v *InterfaceValidator) Validate(value interface{}) (interface{}, error)

type LossyUint64Validator

type LossyUint64Validator struct {
	MinVal uint64
	MaxVal uint64
}

func LossyUint64

func LossyUint64() *LossyUint64Validator

Validate numbers as a uint64. In this process they will be stored as a float64, which can lead to a loss of precision as high as 1024(?).

func (*LossyUint64Validator) Max

func (v *LossyUint64Validator) Max(max uint64)

func (*LossyUint64Validator) Min

func (v *LossyUint64Validator) Min(min uint64)

func (*LossyUint64Validator) Validate

func (v *LossyUint64Validator) Validate(value interface{}) (interface{}, error)

type MapMap

type MapMap struct {
	Contains TypeMap
}

func (MapMap) Marshal

func (mm MapMap) Marshal(ctx Context, parent *reflect.Value, src reflect.Value) (json.Marshaler, error)

func (MapMap) Unmarshal

func (mm MapMap) Unmarshal(ctx Context, parent *reflect.Value, partial interface{}, dstValue reflect.Value) error

type MappedField

type MappedField struct {
	StructFieldName  string
	StructGetterName string
	JSONFieldName    string
	Contains         TypeMap
	Validator        Validator
	Optional         bool
	ReadOnly         bool
}

type MultiValidationError

type MultiValidationError struct {
	NestedErrors []*FlattenedPathError
}

func (*MultiValidationError) AddError

func (e *MultiValidationError) AddError(err *ValidationError, path ...string)

func (*MultiValidationError) Error

func (e *MultiValidationError) Error() string

func (*MultiValidationError) Errors

type ParameterMap

type ParameterMap struct {
	StructFieldName string
	ParameterName   string
	Mapper          QueryParameterMapper
	OmitEmpty       bool
}

ParameterMap corresponds to each field in a specific struct, it requires struct's name and the corresponding key value in the URL query

type PrimitiveMap

type PrimitiveMap struct {
	V Validator
	// contains filtered or unexported fields
}

func (*PrimitiveMap) Marshal

func (m *PrimitiveMap) Marshal(ctx Context, parent *reflect.Value, field reflect.Value) (json.Marshaler, error)

func (*PrimitiveMap) Unmarshal

func (m *PrimitiveMap) Unmarshal(ctx Context, parent *reflect.Value, partial interface{}, dstValue reflect.Value) error

type QueryMap

type QueryMap struct {
	UnderlyingType interface{}
	ParameterMaps  []ParameterMap
}

This is the overarching struct used to transform structs into url params and vice versa

func (QueryMap) Decode

func (qm QueryMap) Decode(urlQuery map[string][]string, dst interface{}) error

Taking a URL Query (or any string->[]string struct) and shoving it into the struct as specified by qm.UnderlyingType

func (QueryMap) DecodeHeader

func (qm QueryMap) DecodeHeader(headers http.Header, dst interface{}) error

func (QueryMap) Encode

func (qm QueryMap) Encode(src interface{}, urlQuery map[string][]string) error

Taking a struct and turning it into a url param. The precise mechanisms of doing so are are defined in the individual ParameterMap

func (QueryMap) EncodeHeader

func (qm QueryMap) EncodeHeader(src interface{}, headers http.Header) error

This ignores the case of parameter name in favor of the canonical format of http.Header

type QueryParameterMapper

type QueryParameterMapper interface {
	Encode(reflect.Value) ([]string, error)
	Decode(...string) (interface{}, error)
}

QueryParameterMapper defines how url.Values value ([]string) and struct are to be transformed into each other. It is from a slice of strings, reflecting the structure of url.Values. These can be specified by their type (whichever struct the Parameter mapper will be, and the restrictions defined on the type, defined by Validators slice below)

type RawMessage

type RawMessage struct {
	Data []byte
}

func (RawMessage) MarshalJSON

func (rm RawMessage) MarshalJSON() ([]byte, error)

type RegisterableTypeMap

type RegisterableTypeMap interface {
	TypeMap
	GetUnderlyingType() reflect.Type
}

type RenderInfo

type RenderInfo struct {
	Context Context
	Parent  interface{}
	Value   interface{}
}

type SliceMap

type SliceMap struct {
	Contains TypeMap
	MinLen   *int
	MaxLen   *int
}

func (SliceMap) Marshal

func (sm SliceMap) Marshal(ctx Context, parent *reflect.Value, src reflect.Value) (json.Marshaler, error)

func (SliceMap) Unmarshal

func (sm SliceMap) Unmarshal(ctx Context, parent *reflect.Value, partial interface{}, dstValue reflect.Value) error

type StrPointerQueryParameterMapper

type StrPointerQueryParameterMapper struct {
	UnderlyingQueryParameterMapper QueryParameterMapper
}

func (StrPointerQueryParameterMapper) Decode

func (pqpm StrPointerQueryParameterMapper) Decode(src ...string) (interface{}, error)

func (StrPointerQueryParameterMapper) Encode

type StrSliceQueryParameterMapper

type StrSliceQueryParameterMapper struct {
	Validators                     []func([]string) bool
	UnderlyingQueryParameterMapper QueryParameterMapper
}

func (StrSliceQueryParameterMapper) Decode

func (sqpm StrSliceQueryParameterMapper) Decode(src ...string) (interface{}, error)

func (StrSliceQueryParameterMapper) Encode

func (sqpm StrSliceQueryParameterMapper) Encode(src reflect.Value) ([]string, error)

type StringQueryParameterMapper

type StringQueryParameterMapper struct {
	Validators []func(string) bool
}

Examples of mappers

func (StringQueryParameterMapper) Decode

func (sqpm StringQueryParameterMapper) Decode(src ...string) (interface{}, error)

func (StringQueryParameterMapper) Encode

func (sqpm StringQueryParameterMapper) Encode(src reflect.Value) ([]string, error)

type StringValidator

type StringValidator struct {
	MinLen   int
	MaxLen   int
	RE       *regexp.Regexp
	REErrMsg string
}

func String

func String(minLen int, maxLen int) *StringValidator

func (*StringValidator) Regex

func (*StringValidator) RegexError

func (v *StringValidator) RegexError(re *regexp.Regexp, errMsg string) *StringValidator

func (*StringValidator) Validate

func (v *StringValidator) Validate(value interface{}) (interface{}, error)

func (*StringValidator) ValidateString

func (v *StringValidator) ValidateString(s string) (string, error)

type StringsSliceMapper

type StringsSliceMapper struct {
	StringValidator *StringValidator
}

func (*StringsSliceMapper) Marshal

func (s *StringsSliceMapper) Marshal(ctx Context, parent *reflect.Value, src reflect.Value) (json.Marshaler, error)

func (*StringsSliceMapper) Unmarshal

func (ss *StringsSliceMapper) Unmarshal(ctx Context, parent *reflect.Value, partial interface{}, dstValue reflect.Value) error

type StructMap

type StructMap struct {
	UnderlyingType interface{}
	Fields         []MappedField
}

func (StructMap) GetUnderlyingType

func (sm StructMap) GetUnderlyingType() reflect.Type

func (StructMap) Marshal

func (sm StructMap) Marshal(ctx Context, parent *reflect.Value, src reflect.Value) (json.Marshaler, error)

func (StructMap) Unmarshal

func (sm StructMap) Unmarshal(ctx Context, parent *reflect.Value, partial interface{}, dstValue reflect.Value) error

type TimeMap

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

func (*TimeMap) Marshal

func (m *TimeMap) Marshal(ctx Context, parent *reflect.Value, field reflect.Value) (json.Marshaler, error)

func (*TimeMap) Unmarshal

func (m *TimeMap) Unmarshal(ctx Context, parent *reflect.Value, partial interface{}, dstValue reflect.Value) error

type TimeQueryParameterMapper

type TimeQueryParameterMapper struct {
	Validators []func(time.Time) bool
}

func (TimeQueryParameterMapper) Decode

func (tqpm TimeQueryParameterMapper) Decode(src ...string) (interface{}, error)

func (TimeQueryParameterMapper) Encode

func (tqpm TimeQueryParameterMapper) Encode(src reflect.Value) ([]string, error)

type TypeMap

type TypeMap interface {
	Unmarshal(ctx Context, parent *reflect.Value, partial interface{}, dstValue reflect.Value) error
	Marshal(ctx Context, parent *reflect.Value, field reflect.Value) (json.Marshaler, error)
}

func MapOf

func MapOf(elem TypeMap) TypeMap

func NewPrimitiveMap

func NewPrimitiveMap(v Validator) TypeMap

func NewStringsSliceMapper

func NewStringsSliceMapper(sv *StringValidator) TypeMap

Used for StringsArray, which has a "V" field containing []string. Optionally can take a string validator to apply to each entry.

func SliceOf

func SliceOf(elem TypeMap) TypeMap

func SliceOfMax

func SliceOfMax(elem TypeMap, max int) TypeMap

func SliceOfMin

func SliceOfMin(elem TypeMap, min int) TypeMap

func SliceOfRange

func SliceOfRange(elem TypeMap, min, max int) TypeMap

func Time

func Time() TypeMap

func VariableType

func VariableType(switchOnFieldName string, types map[string]TypeMap) TypeMap

type TypeMapper

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

func NewTypeMapper

func NewTypeMapper(maps ...RegisterableTypeMap) *TypeMapper

func (*TypeMapper) Marshal

func (tm *TypeMapper) Marshal(ctx Context, src interface{}) ([]byte, error)

func (*TypeMapper) MarshalIndent

func (tm *TypeMapper) MarshalIndent(ctx Context, src interface{}, prefix, indent string) ([]byte, error)

func (*TypeMapper) Unmarshal

func (tm *TypeMapper) Unmarshal(ctx Context, data []byte, dest interface{}) error

type UUIDStringValidator

type UUIDStringValidator struct{}

func UUIDString

func UUIDString() *UUIDStringValidator

func (*UUIDStringValidator) Validate

func (v *UUIDStringValidator) Validate(value interface{}) (interface{}, error)

func (*UUIDStringValidator) ValidateString

func (v *UUIDStringValidator) ValidateString(value string) (string, error)

type UintQueryParameterMapper

type UintQueryParameterMapper struct {
	Validators []func(uint64) bool
	BitSize    int
}

func (UintQueryParameterMapper) Decode

func (uqpm UintQueryParameterMapper) Decode(src ...string) (interface{}, error)

func (UintQueryParameterMapper) Encode

func (uqpm UintQueryParameterMapper) Encode(src reflect.Value) ([]string, error)

type ValidationError

type ValidationError struct {
	Field        string
	Message      string
	NestedErrors []*ValidationError
}

func NewValidationError

func NewValidationError(reason string, a ...interface{}) *ValidationError

func NewValidationErrorWithField

func NewValidationErrorWithField(field, message string) *ValidationError

func (*ValidationError) AddError

func (e *ValidationError) AddError(err *ValidationError)

func (*ValidationError) Error

func (e *ValidationError) Error() string

func (*ValidationError) ErrorMessage

func (e *ValidationError) ErrorMessage() string

func (*ValidationError) Flatten

func (e *ValidationError) Flatten() *MultiValidationError

func (*ValidationError) SetField

func (e *ValidationError) SetField(field string)

type Validator

type Validator interface {
	Validate(interface{}) (interface{}, error)
}

func Boolean

func Boolean() Validator

func Integer

func Integer(minVal, maxVal int64) Validator

func KeyFromVariableTypeMap

func KeyFromVariableTypeMap(m map[string]TypeMap) Validator

func OneOf

func OneOf(allowed ...string) Validator

Jump to

Keyboard shortcuts

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