Skip to content

cosiner/go-schema

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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.

About

No description or website provided.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages