schema

package
v1.14.2 Latest Latest
Warning

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

Go to latest
Published: May 20, 2023 License: MIT Imports: 11 Imported by: 11

README

Golang recursive schema

Library allows to write code that work with any type of schemas. Regardless if those are JSON, XML, YAML, or golang structs.

Most benefits

  • Union types can be deserialized into interface field

How to convert between json <-> go

data := `{"name": "John", "cars": [{"name":"Ford"}]}`
schema := schema.FromJSON(data)
nativego, err := schema.ToGo(schema)

expected := map[string]any{
    "name": "John",
    "cars": []any{
        map[string]any{
            "name": "Ford",
        },
    },
}
assert.Equal(t, expected, nativego)

How to convert schema into named golang struct?

This example shows how to convert only part of schema to golang struct. List of cars will have type Car when parent Person object will be map[string]any.

type Car struct {
    Name string
}
nativego := schema.MustToGo(schema, WithOnlyTheseRules(
	WhenPath([]string{"cars", "[*]"}, UseStruct(Car{}))))

expected := map[string]any{
    "name": "John",
    "cars": []any{
        Car{
            Name: "Ford",
        },
    },
}
assert.Equal(t, expected, nativego)

How to define custom serialization and deserilization?

Currently, ser-deser operations are available on maps. This is current design decision, it might change in the future.

type Car struct {
    Name string
}

// make sure to Car implements schema.Marshaler and schema.Unmarshaler
var (
	_ schema.Marshaler = (*Car)(nil)
    _ schema.Unmarshaler = (*Car)(nil)
)

func (c *Car) MarshalSchema() (schema.*Map, error) {
    return schema.MkMap(map[string]schema.Schema{
        "name": schema.MkString(c.Name),
    }), nil
}

func (c *Car) UnmarshalSchema(x schema.*Map) error {
    for _, field := range x.Field {
        switch key {
        case "name":
            c.Name = s.MustToString()
        default:
            return fmt.Errorf("unknown key %s", key)
        }
    }
	
    return nil
}

Roadmap

V0.1.0
  • Json <-> Schema <-> Go (with structs mapping)
  • Write test with wrong type conversions
  • Value are split into Number(Int, Float), String, Bool, and Null
  • Default schema registry + mkunion make union serialization/deserialization work transperently
  • Support pointers *string, etc.
  • Support DynamoDB (FromDynamoDB, ToDynamoDB)
  • Support for pointer to types like *string, *int, etc.
  • Support for relative paths like WhenPath([]string{"*", "ListOfCars", "Car"}, UseStruct(Car{})). Absolute paths are without * at the beginning.
V0.2.x
  • Support options for ToGo & FromGo like WithOnlyTheseRules, WithExtraRules, WithDefaultMapDef, etc. Gives better control on how schema is converted to golang. It's especially important from security reasons, whey you want to allow rules only whitelisted rules, for user generated json input.
  • Schema support interface for custom type-setters, that don't require reflection, and mkunion can leverage them. Use UseTypeDef eg. WhenPath([]string{}, UseTypeDef(&someTypeDef{})),
  • Support for how union names should be expressed in schema WithUnionFormatter(func(t reflect.Type) string)
V0.3.x
  • schema.Compare method to compare two schemas
V0.4.x
  • Support for Binary type
  • Add missing function for MkBinary, MkFloat, MkNone
V0.5.x
  • schema.UnwrapDynamoDB takes DynamoDB specific nesting and removes it.
  • Eliminate data races in *UnionVariants[A] -> MapDefFor & UseUnionFormatter data race
  • Introduce ToGoG[T any] function, that makes ToGo with type assertion and tries to convert to T
  • Rename schema.As to schema.AsDefault and make schema.As as variant that returns false, if type is not supported
V0.6.x
  • Support serialization of schema.Marchaler to schema.Unmarshaller, that can dramatically improve performance in some cases. Limitation of current implementation is that it works only on *Map, and don't allow custom ser-deser on other types. It's not hard decision. It's just that I don't have use case for other types yet.
V0.7.x
  • schema.ToGo can deduce nested types, for fields in struct that have type information
  • Generator of custom ser-deser that improve performance and developer experiences for free
V0.8.x
  • Support json tags in golang to map field names to schema
  • Add cata, ana, and hylo morphisms
  • Open goConfigFunc to allow customizing how golang types are converted to schema, passed from external code.

Documentation

Overview

Code generated by mkunion. DO NOT EDIT.

Code generated by mkunion. DO NOT EDIT.

Code generated by mkunion. DO NOT EDIT.

Code generated by mkunion. DO NOT EDIT.

Code generated by mkunion. DO NOT EDIT.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func As added in v1.9.0

func As[A int | int8 | int16 | int32 | int64 |
	uint | uint8 | uint16 | uint32 | uint64 |
	float32 | float64 |
	bool | string | []byte](x Schema) (A, bool)

func AsDefault added in v1.12.0

func AsDefault[A int | int8 | int16 | int32 | int64 |
	uint | uint8 | uint16 | uint32 | uint64 |
	float32 | float64 |
	bool | string | []byte](x Schema, def A) A

func Compare added in v1.10.0

func Compare(a, b Schema) int

func FormatUnionNameUsingFullName added in v1.9.0

func FormatUnionNameUsingFullName(t reflect.Type) string

func FormatUnionNameUsingTypeName added in v1.9.0

func FormatUnionNameUsingTypeName(t reflect.Type) string

func FormatUnionNameUsingTypeNameWithPackage added in v1.9.0

func FormatUnionNameUsingTypeNameWithPackage(t reflect.Type) string

func MatchSchema added in v1.10.0

func MatchSchema[TOut any](
	x Schema,
	f1 func(x *None) TOut,
	f2 func(x *Bool) TOut,
	f3 func(x *Number) TOut,
	f4 func(x *String) TOut,
	f5 func(x *Binary) TOut,
	f6 func(x *List) TOut,
	f7 func(x *Map) TOut,
	df func(x Schema) TOut,
) TOut

func MatchSchemaR2 added in v1.10.0

func MatchSchemaR2[TOut1, TOut2 any](
	x Schema,
	f1 func(x *None) (TOut1, TOut2),
	f2 func(x *Bool) (TOut1, TOut2),
	f3 func(x *Number) (TOut1, TOut2),
	f4 func(x *String) (TOut1, TOut2),
	f5 func(x *Binary) (TOut1, TOut2),
	f6 func(x *List) (TOut1, TOut2),
	f7 func(x *Map) (TOut1, TOut2),
	df func(x Schema) (TOut1, TOut2),
) (TOut1, TOut2)

func MustMatchSchema added in v1.7.3

func MustMatchSchema[TOut any](
	x Schema,
	f1 func(x *None) TOut,
	f2 func(x *Bool) TOut,
	f3 func(x *Number) TOut,
	f4 func(x *String) TOut,
	f5 func(x *Binary) TOut,
	f6 func(x *List) TOut,
	f7 func(x *Map) TOut,
) TOut

func MustMatchSchemaR0 added in v1.14.1

func MustMatchSchemaR0(
	x Schema,
	f1 func(x *None),
	f2 func(x *Bool),
	f3 func(x *Number),
	f4 func(x *String),
	f5 func(x *Binary),
	f6 func(x *List),
	f7 func(x *Map),
)

func MustMatchSchemaR2 added in v1.7.3

func MustMatchSchemaR2[TOut1, TOut2 any](
	x Schema,
	f1 func(x *None) (TOut1, TOut2),
	f2 func(x *Bool) (TOut1, TOut2),
	f3 func(x *Number) (TOut1, TOut2),
	f4 func(x *String) (TOut1, TOut2),
	f5 func(x *Binary) (TOut1, TOut2),
	f6 func(x *List) (TOut1, TOut2),
	f7 func(x *Map) (TOut1, TOut2),
) (TOut1, TOut2)

func MustToGo added in v1.9.0

func MustToGo(x Schema, options ...goConfigFunc) any

func Reduce added in v1.7.7

func Reduce[A any](data Schema, init A, fn func(Schema, A) A) A

func ReduceSchemaBreadthFirst added in v1.7.3

func ReduceSchemaBreadthFirst[A any](r SchemaReducer[A], v Schema, init A) A

func ReduceSchemaDepthFirst added in v1.7.3

func ReduceSchemaDepthFirst[A any](r SchemaReducer[A], v Schema, init A) A

func RegisterRules added in v1.7.2

func RegisterRules(xs []RuleMatcher)

func RegisterUnionTypes added in v1.9.0

func RegisterUnionTypes[A any](x *UnionVariants[A])

func SetDefaultUnionTypeFormatter added in v1.9.0

func SetDefaultUnionTypeFormatter(f UnionFormatFunc)

func ToDynamoDB added in v1.7.7

func ToDynamoDB(x Schema) types.AttributeValue

func ToGo added in v1.7.2

func ToGo(x Schema, options ...goConfigFunc) (any, error)

func ToGoG added in v1.12.0

func ToGoG[A any](x Schema, options ...goConfigFunc) (A, error)

ToGoG converts a Schema to a Go value of the given type.

func ToJSON added in v1.7.2

func ToJSON(schema Schema) ([]byte, error)

func WithDefaultListDef added in v1.9.0

func WithDefaultListDef(def TypeListDefinition) goConfigFunc

func WithDefaultMaoDef added in v1.9.0

func WithDefaultMaoDef(def TypeMapDefinition) goConfigFunc

func WithExtraRules added in v1.9.0

func WithExtraRules(rules ...RuleMatcher) goConfigFunc

func WithOnlyTheseRules added in v1.9.0

func WithOnlyTheseRules(rules ...RuleMatcher) goConfigFunc

func WithRulesFromRegistry added in v1.9.0

func WithRulesFromRegistry(registry *Registry) goConfigFunc

func WithUnionFormatter added in v1.9.0

func WithUnionFormatter(f UnionFormatFunc) goConfigFunc

func WithoutDefaultRegistry added in v1.9.0

func WithoutDefaultRegistry() goConfigFunc

Types

type Binary added in v1.11.0

type Binary struct{ B []byte }

func MkBinary added in v1.11.0

func MkBinary(b []byte) *Binary

func (*Binary) Accept added in v1.11.0

func (r *Binary) Accept(v SchemaVisitor) any

type Bool

type Bool bool

func MkBool added in v1.10.0

func MkBool(b bool) *Bool

func (*Bool) Accept added in v1.7.3

func (r *Bool) Accept(v SchemaVisitor) any

type Field

type Field struct {
	Name  string
	Value Schema
}

func MkField added in v1.10.0

func MkField(name string, value Schema) Field

type List

type List struct {
	Items []Schema
}

func MkList added in v1.10.0

func MkList(items ...Schema) *List

func (*List) Accept added in v1.7.3

func (r *List) Accept(v SchemaVisitor) any

type ListBuilder added in v1.9.0

type ListBuilder interface {
	Append(value any) error
	Build() any
}

type Map

type Map struct {
	Field []Field
}

func MkMap added in v1.10.0

func MkMap(fields ...Field) *Map

func (*Map) Accept added in v1.7.3

func (r *Map) Accept(v SchemaVisitor) any

type MapBuilder added in v1.9.0

type MapBuilder interface {
	Set(key string, value any) error
	Build() any
}

type Marshaler added in v1.13.0

type Marshaler interface {
	MarshalSchema() (*Map, error)
}

type NativeList

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

func (*NativeList) Append added in v1.9.0

func (s *NativeList) Append(value any) error

func (*NativeList) Build added in v1.9.0

func (s *NativeList) Build() any

func (*NativeList) NewListBuilder added in v1.9.0

func (s *NativeList) NewListBuilder() ListBuilder

type NativeMap

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

func (*NativeMap) Build added in v1.9.0

func (s *NativeMap) Build() any

func (*NativeMap) NewMapBuilder added in v1.9.0

func (s *NativeMap) NewMapBuilder() MapBuilder

func (*NativeMap) Set

func (s *NativeMap) Set(k string, value any) error

type None

type None struct{}

func MkNone added in v1.11.0

func MkNone() *None

func (*None) Accept added in v1.7.3

func (r *None) Accept(v SchemaVisitor) any

type Number

type Number float64

func MkFloat added in v1.11.0

func MkFloat(x float64) *Number

func MkInt

func MkInt(x int) *Number

func (*Number) Accept added in v1.7.3

func (r *Number) Accept(v SchemaVisitor) any

type Registry added in v1.7.2

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

func NewRegistry added in v1.7.2

func NewRegistry() *Registry

func (*Registry) RegisterRules added in v1.7.2

func (r *Registry) RegisterRules(xs []RuleMatcher)

func (*Registry) SetUnionTypeFormatter added in v1.9.0

func (r *Registry) SetUnionTypeFormatter(f UnionFormatFunc)

type RuleMatcher

type RuleMatcher interface {
	MapDefFor(x *Map, path []string, config *goConfig) (TypeMapDefinition, bool)
	SchemaToUnionType(x any, schema Schema, config *goConfig) (Schema, bool)
}

type Schema added in v1.7.3

type Schema interface {
	Accept(g SchemaVisitor) any
}

func FromDynamoDB added in v1.7.7

func FromDynamoDB(x types.AttributeValue) (Schema, error)

func FromGo added in v1.7.3

func FromGo(x any, options ...goConfigFunc) Schema

func FromJSON added in v1.7.3

func FromJSON(data []byte) (Schema, error)

func Get added in v1.9.0

func Get(data Schema, location string) Schema

func UnwrapDynamoDB added in v1.12.0

func UnwrapDynamoDB(data Schema) (Schema, error)

type SchemaBreadthFirstVisitor added in v1.7.3

type SchemaBreadthFirstVisitor[A any] struct {
	// contains filtered or unexported fields
}

func (*SchemaBreadthFirstVisitor[A]) VisitBinary added in v1.11.0

func (d *SchemaBreadthFirstVisitor[A]) VisitBinary(v *Binary) any

func (*SchemaBreadthFirstVisitor[A]) VisitBool added in v1.7.3

func (d *SchemaBreadthFirstVisitor[A]) VisitBool(v *Bool) any

func (*SchemaBreadthFirstVisitor[A]) VisitList added in v1.7.3

func (d *SchemaBreadthFirstVisitor[A]) VisitList(v *List) any

func (*SchemaBreadthFirstVisitor[A]) VisitMap added in v1.7.3

func (d *SchemaBreadthFirstVisitor[A]) VisitMap(v *Map) any

func (*SchemaBreadthFirstVisitor[A]) VisitNone added in v1.7.3

func (d *SchemaBreadthFirstVisitor[A]) VisitNone(v *None) any

func (*SchemaBreadthFirstVisitor[A]) VisitNumber added in v1.7.3

func (d *SchemaBreadthFirstVisitor[A]) VisitNumber(v *Number) any

func (*SchemaBreadthFirstVisitor[A]) VisitString added in v1.7.3

func (d *SchemaBreadthFirstVisitor[A]) VisitString(v *String) any

type SchemaDefaultReduction added in v1.7.3

type SchemaDefaultReduction[A any] struct {
	PanicOnFallback      bool
	DefaultStopReduction bool
	OnNone               func(x *None, agg A) (result A, stop bool)
	OnBool               func(x *Bool, agg A) (result A, stop bool)
	OnNumber             func(x *Number, agg A) (result A, stop bool)
	OnString             func(x *String, agg A) (result A, stop bool)
	OnBinary             func(x *Binary, agg A) (result A, stop bool)
	OnList               func(x *List, agg A) (result A, stop bool)
	OnMap                func(x *Map, agg A) (result A, stop bool)
}

func (*SchemaDefaultReduction[A]) ReduceBinary added in v1.11.0

func (t *SchemaDefaultReduction[A]) ReduceBinary(x *Binary, agg A) (result A, stop bool)

func (*SchemaDefaultReduction[A]) ReduceBool added in v1.7.3

func (t *SchemaDefaultReduction[A]) ReduceBool(x *Bool, agg A) (result A, stop bool)

func (*SchemaDefaultReduction[A]) ReduceList added in v1.7.3

func (t *SchemaDefaultReduction[A]) ReduceList(x *List, agg A) (result A, stop bool)

func (*SchemaDefaultReduction[A]) ReduceMap added in v1.7.3

func (t *SchemaDefaultReduction[A]) ReduceMap(x *Map, agg A) (result A, stop bool)

func (*SchemaDefaultReduction[A]) ReduceNone added in v1.7.3

func (t *SchemaDefaultReduction[A]) ReduceNone(x *None, agg A) (result A, stop bool)

func (*SchemaDefaultReduction[A]) ReduceNumber added in v1.7.3

func (t *SchemaDefaultReduction[A]) ReduceNumber(x *Number, agg A) (result A, stop bool)

func (*SchemaDefaultReduction[A]) ReduceString added in v1.7.3

func (t *SchemaDefaultReduction[A]) ReduceString(x *String, agg A) (result A, stop bool)

type SchemaDefaultVisitor added in v1.7.3

type SchemaDefaultVisitor[A any] struct {
	Default  A
	OnNone   func(x *None) A
	OnBool   func(x *Bool) A
	OnNumber func(x *Number) A
	OnString func(x *String) A
	OnBinary func(x *Binary) A
	OnList   func(x *List) A
	OnMap    func(x *Map) A
}

func (*SchemaDefaultVisitor[A]) VisitBinary added in v1.11.0

func (t *SchemaDefaultVisitor[A]) VisitBinary(v *Binary) any

func (*SchemaDefaultVisitor[A]) VisitBool added in v1.7.3

func (t *SchemaDefaultVisitor[A]) VisitBool(v *Bool) any

func (*SchemaDefaultVisitor[A]) VisitList added in v1.7.3

func (t *SchemaDefaultVisitor[A]) VisitList(v *List) any

func (*SchemaDefaultVisitor[A]) VisitMap added in v1.7.3

func (t *SchemaDefaultVisitor[A]) VisitMap(v *Map) any

func (*SchemaDefaultVisitor[A]) VisitNone added in v1.7.3

func (t *SchemaDefaultVisitor[A]) VisitNone(v *None) any

func (*SchemaDefaultVisitor[A]) VisitNumber added in v1.7.3

func (t *SchemaDefaultVisitor[A]) VisitNumber(v *Number) any

func (*SchemaDefaultVisitor[A]) VisitString added in v1.7.3

func (t *SchemaDefaultVisitor[A]) VisitString(v *String) any

type SchemaDepthFirstVisitor added in v1.7.3

type SchemaDepthFirstVisitor[A any] struct {
	// contains filtered or unexported fields
}

func (*SchemaDepthFirstVisitor[A]) VisitBinary added in v1.11.0

func (d *SchemaDepthFirstVisitor[A]) VisitBinary(v *Binary) any

func (*SchemaDepthFirstVisitor[A]) VisitBool added in v1.7.3

func (d *SchemaDepthFirstVisitor[A]) VisitBool(v *Bool) any

func (*SchemaDepthFirstVisitor[A]) VisitList added in v1.7.3

func (d *SchemaDepthFirstVisitor[A]) VisitList(v *List) any

func (*SchemaDepthFirstVisitor[A]) VisitMap added in v1.7.3

func (d *SchemaDepthFirstVisitor[A]) VisitMap(v *Map) any

func (*SchemaDepthFirstVisitor[A]) VisitNone added in v1.7.3

func (d *SchemaDepthFirstVisitor[A]) VisitNone(v *None) any

func (*SchemaDepthFirstVisitor[A]) VisitNumber added in v1.7.3

func (d *SchemaDepthFirstVisitor[A]) VisitNumber(v *Number) any

func (*SchemaDepthFirstVisitor[A]) VisitString added in v1.7.3

func (d *SchemaDepthFirstVisitor[A]) VisitString(v *String) any

type SchemaReducer added in v1.7.3

type SchemaReducer[A any] interface {
	ReduceNone(x *None, agg A) (result A, stop bool)
	ReduceBool(x *Bool, agg A) (result A, stop bool)
	ReduceNumber(x *Number, agg A) (result A, stop bool)
	ReduceString(x *String, agg A) (result A, stop bool)
	ReduceBinary(x *Binary, agg A) (result A, stop bool)
	ReduceList(x *List, agg A) (result A, stop bool)
	ReduceMap(x *Map, agg A) (result A, stop bool)
}

type SchemaVisitor added in v1.7.3

type SchemaVisitor interface {
	VisitNone(v *None) any
	VisitBool(v *Bool) any
	VisitNumber(v *Number) any
	VisitString(v *String) any
	VisitBinary(v *Binary) any
	VisitList(v *List) any
	VisitMap(v *Map) any
}

type SelfUnmarshallingStructBuilder added in v1.13.0

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

func UseSelfUnmarshallingStruct added in v1.13.0

func UseSelfUnmarshallingStruct(new func() Unmarshaler) *SelfUnmarshallingStructBuilder

func (*SelfUnmarshallingStructBuilder) NewMapBuilder added in v1.13.0

func (c *SelfUnmarshallingStructBuilder) NewMapBuilder() MapBuilder

type String

type String string

func MkString

func MkString(s string) *String

func (*String) Accept added in v1.7.3

func (r *String) Accept(v SchemaVisitor) any

type StructBuilder added in v1.9.0

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

func (*StructBuilder) Build added in v1.9.0

func (s *StructBuilder) Build() any

func (*StructBuilder) Set added in v1.9.0

func (s *StructBuilder) Set(key string, value any) error

type StructDefinition added in v1.9.0

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

func (*StructDefinition) NewMapBuilder added in v1.9.0

func (s *StructDefinition) NewMapBuilder() MapBuilder

type TypeListDefinition added in v1.9.0

type TypeListDefinition interface {
	NewListBuilder() ListBuilder
}

type TypeMapDefinition added in v1.9.0

type TypeMapDefinition interface {
	NewMapBuilder() MapBuilder
}

func UseReflectionUnmarshallingStruct added in v1.13.0

func UseReflectionUnmarshallingStruct(t any) TypeMapDefinition

func UseStruct

func UseStruct(t any) TypeMapDefinition

func UseTypeDef added in v1.9.0

func UseTypeDef(definition TypeMapDefinition) TypeMapDefinition

type UnionFormatFunc added in v1.9.0

type UnionFormatFunc func(t reflect.Type) string

type UnionMap added in v1.9.0

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

func (*UnionMap) Build added in v1.9.0

func (u *UnionMap) Build() any

func (*UnionMap) NewMapBuilder added in v1.9.0

func (u *UnionMap) NewMapBuilder() MapBuilder

func (*UnionMap) Set added in v1.9.0

func (u *UnionMap) Set(key string, value any) error

type UnionVariants added in v1.9.0

type UnionVariants[A any] struct {
	// contains filtered or unexported fields
}

func MustDefineUnion added in v1.9.0

func MustDefineUnion[A any](xs ...A) *UnionVariants[A]

func (*UnionVariants[A]) MapDefFor added in v1.9.0

func (u *UnionVariants[A]) MapDefFor(x *Map, path []string, config *goConfig) (TypeMapDefinition, bool)

func (*UnionVariants[A]) SchemaToUnionType added in v1.9.0

func (u *UnionVariants[A]) SchemaToUnionType(x any, schema Schema, config *goConfig) (Schema, bool)

type Unmarshaler added in v1.13.0

type Unmarshaler interface {
	UnmarshalSchema(x *Map) error
}

type WhenField

type WhenField[A any] struct {
	// contains filtered or unexported fields
}

func WhenPath

func WhenPath(path []string, setter TypeMapDefinition) *WhenField[struct{}]

func (*WhenField[A]) MapDefFor added in v1.9.0

func (r *WhenField[A]) MapDefFor(x *Map, path []string, config *goConfig) (TypeMapDefinition, bool)

func (*WhenField[A]) SchemaToUnionType added in v1.9.0

func (r *WhenField[A]) SchemaToUnionType(x any, schema Schema, config *goConfig) (Schema, bool)

type WrapInMap added in v1.9.0

type WrapInMap[A any] struct {
	ForType A
	InField string
}

func (*WrapInMap[A]) MapDefFor added in v1.9.0

func (w *WrapInMap[A]) MapDefFor(x *Map, path []string, config *goConfig) (TypeMapDefinition, bool)

func (*WrapInMap[A]) SchemaToUnionType added in v1.9.0

func (w *WrapInMap[A]) SchemaToUnionType(x any, schema Schema, config *goConfig) (Schema, bool)

Jump to

Keyboard shortcuts

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