schema

package module
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: Dec 23, 2018 License: MIT Imports: 5 Imported by: 0

README

go-schema

GoDoc Build Status Coverage Status Go Report Card

go-schema is a simple library for go to bind source strings into structures, inspired by gorilla/schema.

Install

go get github.com/cosiner/go-schema

Features

  • implements builtin data types for almost all go primitive types: bool,string,int(8,16,32,64), uint, float...
  • support slice
  • support custom data type by implements specified interface
  • support multiple data source such as url query params, path params, headers, and so on. user can add their own sources by implements specified interface.
  • support anonymous embed structure, structure field, inline structure

FieldTags

// format: sources[;flags], sources: source[,source]*, flags: [inline]
type FieldOptions struct {
	Sources []string
	Inline  bool // for structure field
}

Each source can have it's own name, if not specified, use name of first source or converted field name by default.

Example


type httpRequestSource struct {
	req *http.Request
}

func (h *httpRequestSource) Get(source, name string) []string {
	switch source {
	case "body":
		_ = h.req.ParseForm()
		return h.req.PostForm[name]
	case "query":
		return h.req.URL.Query()[name]
	case "header":
		return h.req.Header[name]
	default:
		return nil
	}
}

type DateType struct{}

func (DateType) DataType() interface{} { return time.Time{} }

func (DateType) Decode(s string) (val interface{}, err error) {
	t, err := time.Parse("2006/01/02", s)
	if err != nil {
		return t, err
	}
	return t, nil
}

func (DateType) Encode(val interface{}) (s string, err error) {
	v, ok := val.(time.Time)
	if !ok {
		return "", fmt.Errorf("invalid data type, expect time.Time, but got %s", reflect.TypeOf(val))
	}
	return v.Format("2006/01/02"), nil
}

func newDecoder() (*schema.Decoder, error) {
	p, err := schema.NewParser("schema", []string{"body", "query", "header"}, func(name string) string {
		if name == "" {
			return ""
		}
		return strings.ToLower(name[:1]) + name[1:]
	})
	if err == nil {
		err = p.RegisterTypes(schema.BuiltinTypes()...)
	}
	if err == nil {
		err = p.RegisterTypes(DateType{})
	}
	if err != nil {
		return nil, err
	}
	return schema.NewDecoder(p)
}

func ExampleDecoder_Decode() {
	type QueryRequest struct {
		Name        string    `schema:"body"`
		Date        time.Time `schema:"body"`
		AccessToken string    `schema:"header" header:"Authorization"`
		Page        uint32    `schema:"query" query:"p"`
	}
	u, err := url.Parse("http://localhost?p=3")
	if err != nil {
		log.Fatal(err)
	}
	httpreq := http.Request{
		URL: u,
		PostForm: url.Values{
			"name": []string{"Someone"},
			"date": []string{"2018/12/25"},
		},
		Header: http.Header{
			"Authorization": []string{"Token"},
		},
	}
	d, err := newDecoder()
	if err != nil {
		log.Fatal(err)
	}
	var reqData QueryRequest
	err = d.Decode(&httpRequestSource{&httpreq}, &reqData)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("%s %s %s %d\n", reqData.Name, reqData.Date.Format("2006-01-02"), reqData.AccessToken, reqData.Page)
	// Output: Someone 2018-12-25 Token 3
}

License

MIT.

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Decoder

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

func NewDecoder

func NewDecoder(p *Parser) (*Decoder, error)

func (*Decoder) Decode

func (d *Decoder) Decode(s DecoderSource, v interface{}) error
Example
type QueryRequest struct {
	Name        string    `schema:"body"`
	Date        time.Time `schema:"body"`
	AccessToken string    `schema:"header" header:"Authorization"`
	Page        uint32    `schema:"query" query:"p"`
}
u, err := url.Parse("http://localhost?p=3")
if err != nil {
	log.Fatal(err)
}
httpreq := http.Request{
	URL: u,
	PostForm: url.Values{
		"name": []string{"Someone"},
		"date": []string{"2018/12/25"},
	},
	Header: http.Header{
		"Authorization": []string{"Token"},
	},
}
d, err := newDecoder()
if err != nil {
	log.Fatal(err)
}
var reqData QueryRequest
err = d.Decode(&httpRequestSource{&httpreq}, &reqData)
if err != nil {
	log.Fatal(err)
}

fmt.Printf("%s %s %s %d\n", reqData.Name, reqData.Date.Format("2006-01-02"), reqData.AccessToken, reqData.Page)
Output:

Someone 2018-12-25 Token 3

type DecoderSource

type DecoderSource interface {
	Get(source, field string) []string
}

type Encoder

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

func NewEncoder

func NewEncoder(p *Parser) (*Encoder, error)

func (*Encoder) Encode

func (e *Encoder) Encode(v interface{}, dst EncoderDestination) error

type EncoderDestination

type EncoderDestination interface {
	Set(source, field string, v []string) (bool, error)
}

type FieldOptions

type FieldOptions struct {
	Sources []string
	Inline  bool
}

format: sources[;flags], sources: source[,source]*, flags: [inline]

type Parser

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

func NewParser

func NewParser(optionsTag string, validSources []string, fieldNameConverter func(string) string) (*Parser, error)

optionsTag is used for retrieve field options, each source can have it's own name, if not specified, use name of first source or converted field name by default.

func (*Parser) Parse

func (p *Parser) Parse(t reflect.Type) (*structureInfo, error)

func (*Parser) RegisterTypes

func (p *Parser) RegisterTypes(types ...Type) error

type Type

type Type interface {
	DataType() interface{}
	Encode(v interface{}) (string, error)
	Decode(v string) (interface{}, error)
}

func BuiltinTypes

func BuiltinTypes() []Type

Jump to

Keyboard shortcuts

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