:steam_locomotive: Decodes url.Values into Go value(s) and Encodes Go value(s) into url.Values. Dual Array and Full map support.

Overview

Package form

Project status Build Status Coverage Status Go Report Card GoDoc License Gitter

Package form Decodes url.Values into Go value(s) and Encodes Go value(s) into url.Values.

It has the following features:

  • Supports map of almost all types.
  • Supports both Numbered and Normal arrays eg. "Array[0]" and just "Array" with multiple values passed.
  • Slice honours the specified index. eg. if "Slice[2]" is the only Slice value passed down, it will be put at index 2; if slice isn't big enough it will be expanded.
  • Array honours the specified index. eg. if "Array[2]" is the only Array value passed down, it will be put at index 2; if array isn't big enough a warning will be printed and value ignored.
  • Only creates objects as necessary eg. if no array or map values are passed down, the array and map are left as their default values in the struct.
  • Allows for Custom Type registration.
  • Handles time.Time using RFC3339 time format by default, but can easily be changed by registering a Custom Type, see below.
  • Handles Encoding & Decoding of almost all Go types eg. can Decode into struct, array, map, int... and Encode a struct, array, map, int...

Common Questions

  • Does it support encoding.TextUnmarshaler? No because TextUnmarshaler only accepts []byte but posted values can have multiple values, so is not suitable.
  • Mixing array/slice with array[idx]/slice[idx], in which order are they parsed? array/slice then array[idx]/slice[idx]

Supported Types ( out of the box )

  • string
  • bool
  • int, int8, int16, int32, int64
  • uint, uint8, uint16, uint32, uint64
  • float32, float64
  • struct and anonymous struct
  • interface{}
  • time.Time - by default using RFC3339
  • a pointer to one of the above types
  • slice, array
  • map
  • custom types can override any of the above types
  • many other types may be supported inherently

NOTE: map, struct and slice nesting are ad infinitum.

Installation

Use go get.

go get github.com/go-playground/form

Then import the form package into your own code.

import "github.com/go-playground/form/v4"

Usage

  • Use symbol . for separating fields/structs. (eg. structfield.field)
  • Use [index or key] for access to index of a slice/array or key for map. (eg. arrayfield[0], mapfield[keyvalue])
<form method="POST">
  <input type="text" name="Name" value="joeybloggs"/>
  <input type="text" name="Age" value="3"/>
  <input type="text" name="Gender" value="Male"/>
  <input type="text" name="Address[0].Name" value="26 Here Blvd."/>
  <input type="text" name="Address[0].Phone" value="9(999)999-9999"/>
  <input type="text" name="Address[1].Name" value="26 There Blvd."/>
  <input type="text" name="Address[1].Phone" value="1(111)111-1111"/>
  <input type="text" name="active" value="true"/>
  <input type="text" name="MapExample[key]" value="value"/>
  <input type="text" name="NestedMap[key][key]" value="value"/>
  <input type="text" name="NestedArray[0][0]" value="value"/>
  <input type="submit"/>
</form>

Examples

Decoding

package main

import (
	"fmt"
	"log"
	"net/url"

	"github.com/go-playground/form/v4"
)

// Address contains address information
type Address struct {
	Name  string
	Phone string
}

// User contains user information
type User struct {
	Name        string
	Age         uint8
	Gender      string
	Address     []Address
	Active      bool `form:"active"`
	MapExample  map[string]string
	NestedMap   map[string]map[string]string
	NestedArray [][]string
}

// use a single instance of Decoder, it caches struct info
var decoder *form.Decoder

func main() {
	decoder = form.NewDecoder()

	// this simulates the results of http.Request's ParseForm() function
	values := parseForm()

	var user User

	// must pass a pointer
	err := decoder.Decode(&user, values)
	if err != nil {
		log.Panic(err)
	}

	fmt.Printf("%#v\n", user)
}

// this simulates the results of http.Request's ParseForm() function
func parseForm() url.Values {
	return url.Values{
		"Name":                []string{"joeybloggs"},
		"Age":                 []string{"3"},
		"Gender":              []string{"Male"},
		"Address[0].Name":     []string{"26 Here Blvd."},
		"Address[0].Phone":    []string{"9(999)999-9999"},
		"Address[1].Name":     []string{"26 There Blvd."},
		"Address[1].Phone":    []string{"1(111)111-1111"},
		"active":              []string{"true"},
		"MapExample[key]":     []string{"value"},
		"NestedMap[key][key]": []string{"value"},
		"NestedArray[0][0]":   []string{"value"},
	}
}

Encoding

package main

import (
	"fmt"
	"log"

	"github.com/go-playground/form/v4"
)

// Address contains address information
type Address struct {
	Name  string
	Phone string
}

// User contains user information
type User struct {
	Name        string
	Age         uint8
	Gender      string
	Address     []Address
	Active      bool `form:"active"`
	MapExample  map[string]string
	NestedMap   map[string]map[string]string
	NestedArray [][]string
}

// use a single instance of Encoder, it caches struct info
var encoder *form.Encoder

func main() {
	encoder = form.NewEncoder()

	user := User{
		Name:   "joeybloggs",
		Age:    3,
		Gender: "Male",
		Address: []Address{
			{Name: "26 Here Blvd.", Phone: "9(999)999-9999"},
			{Name: "26 There Blvd.", Phone: "1(111)111-1111"},
		},
		Active:      true,
		MapExample:  map[string]string{"key": "value"},
		NestedMap:   map[string]map[string]string{"key": {"key": "value"}},
		NestedArray: [][]string{{"value"}},
	}

	// must pass a pointer
	values, err := encoder.Encode(&user)
	if err != nil {
		log.Panic(err)
	}

	fmt.Printf("%#v\n", values)
}

Registering Custom Types

Decoder

decoder.RegisterCustomTypeFunc(func(vals []string) (interface{}, error) {
	return time.Parse("2006-01-02", vals[0])
}, time.Time{})

ADDITIONAL: if a struct type is registered, the function will only be called if a url.Value exists for the struct and not just the struct fields eg. url.Values{"User":"Name%3Djoeybloggs"} will call the custom type function with 'User' as the type, however url.Values{"User.Name":"joeybloggs"} will not.

Encoder

encoder.RegisterCustomTypeFunc(func(x interface{}) ([]string, error) {
	return []string{x.(time.Time).Format("2006-01-02")}, nil
}, time.Time{})

Ignoring Fields

you can tell form to ignore fields using - in the tag

type MyStruct struct {
	Field string `form:"-"`
}

Omitempty

you can tell form to omit empty fields using ,omitempty or FieldName,omitempty in the tag

type MyStruct struct {
	Field  string `form:",omitempty"`
	Field2 string `form:"CustomFieldName,omitempty"`
}

Notes

To maximize compatibility with other systems the Encoder attempts to avoid using array indexes in url.Values if at all possible.

eg.

// A struct field of
Field []string{"1", "2", "3"}

// will be output a url.Value as
"Field": []string{"1", "2", "3"}

and not
"Field[0]": []string{"1"}
"Field[1]": []string{"2"}
"Field[2]": []string{"3"}

// however there are times where it is unavoidable, like with pointers
i := int(1)
Field []*string{nil, nil, &i}

// to avoid index 1 and 2 must use index
"Field[2]": []string{"1"}

Benchmarks

Run on MacBook Pro (15-inch, 2017) using go version go1.10.1 darwin/amd64

NOTE: the 1 allocation and B/op in the first 4 decodes is actually the struct allocating when passing it in, so primitives are actually zero allocation.

go test -run=NONE -bench=. -benchmem=true
goos: darwin
goarch: amd64
pkg: github.com/go-playground/form/benchmarks

BenchmarkSimpleUserDecodeStruct-8                                    	 5000000	       236 ns/op	      64 B/op	       1 allocs/op
BenchmarkSimpleUserDecodeStructParallel-8                            	20000000	        82.1 ns/op	      64 B/op	       1 allocs/op
BenchmarkSimpleUserEncodeStruct-8                                    	 2000000	       627 ns/op	     485 B/op	      10 allocs/op
BenchmarkSimpleUserEncodeStructParallel-8                            	10000000	       223 ns/op	     485 B/op	      10 allocs/op
BenchmarkPrimitivesDecodeStructAllPrimitivesTypes-8                  	 2000000	       724 ns/op	      96 B/op	       1 allocs/op
BenchmarkPrimitivesDecodeStructAllPrimitivesTypesParallel-8          	10000000	       246 ns/op	      96 B/op	       1 allocs/op
BenchmarkPrimitivesEncodeStructAllPrimitivesTypes-8                  	  500000	      3187 ns/op	    2977 B/op	      36 allocs/op
BenchmarkPrimitivesEncodeStructAllPrimitivesTypesParallel-8          	 1000000	      1106 ns/op	    2977 B/op	      36 allocs/op
BenchmarkComplexArrayDecodeStructAllTypes-8                          	  100000	     13748 ns/op	    2248 B/op	     121 allocs/op
BenchmarkComplexArrayDecodeStructAllTypesParallel-8                  	  500000	      4313 ns/op	    2249 B/op	     121 allocs/op
BenchmarkComplexArrayEncodeStructAllTypes-8                          	  200000	     10758 ns/op	    7113 B/op	     104 allocs/op
BenchmarkComplexArrayEncodeStructAllTypesParallel-8                  	  500000	      3532 ns/op	    7113 B/op	     104 allocs/op
BenchmarkComplexMapDecodeStructAllTypes-8                            	  100000	     17644 ns/op	    5305 B/op	     130 allocs/op
BenchmarkComplexMapDecodeStructAllTypesParallel-8                    	  300000	      5470 ns/op	    5308 B/op	     130 allocs/op
BenchmarkComplexMapEncodeStructAllTypes-8                            	  200000	     11155 ns/op	    6971 B/op	     129 allocs/op
BenchmarkComplexMapEncodeStructAllTypesParallel-8                    	  500000	      3768 ns/op	    6971 B/op	     129 allocs/op
BenchmarkDecodeNestedStruct-8                                        	  500000	      2462 ns/op	     384 B/op	      14 allocs/op
BenchmarkDecodeNestedStructParallel-8                                	 2000000	       814 ns/op	     384 B/op	      14 allocs/op
BenchmarkEncodeNestedStruct-8                                        	 1000000	      1483 ns/op	     693 B/op	      16 allocs/op
BenchmarkEncodeNestedStructParallel-8                                	 3000000	       525 ns/op	     693 B/op	      16 allocs/op

Competitor benchmarks can be found here

Complimentary Software

Here is a list of software that compliments using this library post decoding.

  • Validator - Go Struct and Field validation, including Cross Field, Cross Struct, Map, Slice and Array diving.
  • mold - Is a general library to help modify or set data within data structures and other objects.

Package Versioning

I'm jumping on the vendoring bandwagon, you should vendor this package as I will not be creating different version with gopkg.in like allot of my other libraries.

Why? because my time is spread pretty thin maintaining all of the libraries I have + LIFE, it is so freeing not to worry about it and will help me keep pouring out bigger and better things for you the community.

License

Distributed under MIT License, please see license file in code for more details.

Comments
  • Option to ignore all struct fields not explicitly tagged via struct tag

    Option to ignore all struct fields not explicitly tagged via struct tag

    In the README there's a section about ignoring fields by tagging them with form:"-". Would it be possible to add an option to the decoder (like SetTagName(tagName string)) to ignore all struct fields not explicitly tagged with form:"fieldName" (or the custom tag name if set)?

    The problem I see is the unintended injection of data because this library is used with user-generated content and accepts form data. Having a language like Go that is strictly typed goes a long way but I do have to go through all of my models and tag them with form:"-". Still, I know this is my fault and want to thank you for this awesome library!

    The reason I'm asking is that I'm also using these structs that are filled with form data to also transform the data for later usage. Sometimes there's additional fields I add that need to be public to use within the app but are not supposed to be accepted via the form data. I'm also always tagging all fields I accept even if the form field's name is the lowercased version of the struct field name (so technically, I wouldn't have to add the struct tag) but you immediately see what's accepted via a form and what's not when looking at the struct definition.

    If this is a request you'd rather not implement then a few pointers on how to make this safer for me or where you'd start looking in the code. :)

    enhancement question investigation 
    opened by annismckenzie 7
  • Add setting use brackets as a namespace separator

    Add setting use brackets as a namespace separator

    Add a new setting that allows using square brackets as a namespace separator.

    In a company I work for we use square brackets as a struct separator.

    • [*] Tests exist or have been written that cover this particular change.

    @go-playground/admins

    opened by alxfv 6
  • Missing pointer value

    Missing pointer value "0" while encoding struct

    type T struct { X *uint8 form:"x,omitempty" }

    func main() { tx := uint8(0) x := T{&tx} encoder := form.NewEncoder() values, _ := encoder.Encode(x) fmt.Println(values) // blank map }

    If I try to set value to 0, encoder ignores this field

    bug 
    opened by mifanich 6
  • CustomTypeFunc is not called when struct contains keys in query

    CustomTypeFunc is not called when struct contains keys in query

    If you have a query of b[0].Foo=1&b[0].Bar=2 and b is a custom struct then my CustomTypeFunc won't be called. However, if the query is b[0]=Foo%3D1%26Bar%3D2 then it works as expected, but I can't expect the caller to know which structs are custom and which aren't.

    Test/example case:

    package main
    
    import (
    	"net/url"
    	"github.com/go-playground/form"
    )
    
    type B struct {
    	C string
    	d interface{}
    }
    
    type A struct {
    	B []B
    }
    
    func main() {
    	d := form.NewDecoder()
    	d.RegisterCustomTypeFunc(func(s []string) (interface{}, error) {
    		b := B{}
    		q, err := url.ParseQuery(s[0])
    		if err != nil {
    			return nil, err
    		}
    		b.C = q.Get("C")
    		if b.C == "foo" {
    			// obviously you could use d.Decode again, but this is an example
    			b.d = struct {
    				E string
    			}{q.Get("E")}
    		}
    		return b, nil
    	}, B{})
    
    	q := url.Values{}
    	q.Set("B[0].C", "foo")
    	q.Set("B[0].E", "bar")
    	a := &A{}
    	d.Decode(a, q)
    	// RegisterCustomTypeFunc is never called
    	// a is &{B:[{C:foo d:<nil>}]}
    
    	q = url.Values{}
    	q.Set("B[0]", "C=foo&E=bar")
    	a = &A{}
    	d.Decode(a, q)
    	// RegisterCustomTypeFunc is called
    	// a is &{B:[{C:foo d:{E:bar}}]}
    }
    
    investigation 
    opened by jameshartig 6
  • Decode form to specific field?

    Decode form to specific field?

    Say I have the following struct:

    type User struct {
     Address Address
    }
    

    Am I able to decode form data to only the Address field? Like so:

    decoder = form.NewDecoder()
    r.ParseForm()
    var user User
    
    if err := decoder.Decode(&user.Address, r.Form); err != nil {
     panic(err)
    }
    

    Assuming the form data provided is in a suitable format for the User struct.

    question 
    opened by danhardman 6
  • Parse string/int into interface{} ?

    Parse string/int into interface{} ?

    Hello,

    I need to support an older version of an API which supported both application/json and application/x-www-form-urlencoded requests, and some of the request parameters had inconsistent types, e.g. it could be sent as a number or a numeric string. So in order to support both json and forms, as well as numeric strings and numbers, I changed the parameter type to interface{}, however, it is always decoded as nil, presumably because the form type and the target value type do not match (e.g. int/string != interface{}), but I would expect that if I have a parameter of type interface{}, and that parameter is found in the form, then it would store the value in the parameter, since it can hold anything.

    Here is an example:

    package main
    
    import (
    	"bytes"
    	"net/url"
    	"fmt"
    	"io"
    	"github.com/go-playground/form"
    )
    
    type V1Request struct {
    	Application interface{} `json:"application"`
    	DeviceModel string      `json:"deviceModel,omitempty"`
    }
    
    func UrlformConsumerFunc() func(reader io.Reader, v interface{}) error {
    	// create a new form decoder
    	decoder := form.NewDecoder()
    
    	// change tag to json since it's added by default by goswagger
    	decoder.SetTagName("json")
    
    	return func(r io.Reader, v interface{}) error {
    		buf := new(bytes.Buffer)
    		buf.ReadFrom(r)
    
    		values, err := url.ParseQuery(buf.String())
    		if err != nil {
    			return err
    		}
    
    		return decoder.Decode(v, values)
    	}
    }
    
    func main() {
    	consumer := UrlformConsumerFunc()
    	req := V1Request{}
    
    	query := bytes.NewBufferString("application=5&deviceModel=iPhone")
    	consumer(query, &req)
    
    	fmt.Printf("Converted value %#v\n", req)
    }
    

    The output of this will be:

    Converted value main.V1Request{Application:interface {}(nil), DeviceModel:"iPhone"}
    

    Is there any way to achieve this using the library?

    Thanks!

    enhancement 
    opened by Xzya 5
  • Custom decoder accepts slice of string but expected to return single item

    Custom decoder accepts slice of string but expected to return single item

    What is the reason to feed custom decoder with slice of strings?

    type DecodeCustomTypeFunc func([]string) (interface{}, error)
    

    Decoder function is called at

    func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx int) (set bool) {
    

    https://github.com/go-playground/form/blob/master/decoder.go#L191

    If target field is a slice, setFieldByType is called in a loop with idx iterating through []string. Internally custom decoder is called with that full []string and without any mention of current idx.

    How decoder function is expected to deal with multi-element input?

    To me it seems correct code should be

    	val, err := cf([]string{arr[idx]})
    

    but then I'm not sure why decoder function needs to accept a slice.

    bug 
    opened by vearutop 4
  • Single array param set all elements instead of one

    Single array param set all elements instead of one

    func TestDecodeArrayBug33(t *testing.T) {
    	var data struct {
    		A [3]string
    	}
    	cases := []struct {
    		values url.Values
    		want   [3]string
    	}{
    		{url.Values{"A": {"10"}},
    			[3]string{"10", "", ""}},   // Output: [10 10 10]
    		{url.Values{"A": {"10", "20"}},
    			[3]string{"10", "20", ""}}, // Output: [10 10 10]
    		{url.Values{"A[1]": {"20"}},
    			[3]string{"", "20", ""}},   // Output: [ 20 ]
    		{url.Values{"A": {"10"}, "A[2]": {"30"}},
    			[3]string{"10", "", "30"}}, // Output: [10 10 30]
    	}
    	for _, v := range cases {
    		data.A = [3]string{}
    		form.NewDecoder().Decode(&data, v.values)
    		t.Log(data.A)
    	}
    }
    
    opened by powerman 4
  • How to add a new item to a slice?

    How to add a new item to a slice?

    In a HTML form, how do I represent a new (to be added) item for a slice?

    I've tried name="Languages[].Country", where the index isn't defined. As well as providing an index that doesn't exist, neither seem to work.

    opened by danhardman 4
  • Decode shouldn't panic

    Decode shouldn't panic

    It seems that Decode panics if it receives invalid input. It is not idiomatic go and should be refactored using return errors. Otherwise at least the behaviour should be documented so that the caller can guard it with recover.

    enhancement investigation 
    opened by themihai 4
  • Starting an array at an arbitrary number is an opportunity for DoS attacks

    Starting an array at an arbitrary number is an opportunity for DoS attacks

    I'm referring to this feature here:

    Array honours the specified index. eg. if "Array[2]" is the only Array value passed down, it will be put at index 2; if array isn't big enough it will be expanded.

    If a user submits a key like Array[1234567890], the application will allocate over 1G of memory just for this single request. Of course, no one is stopping users from putting an even higher number as an index.

    This snippet demonstrates the problem:

    package main
    
    import (
        "log"
        "net/url"
    
        "github.com/go-playground/form"
    )
    
    type A struct {
        Array []int
    }
    
    func main() {
        decoder := form.NewDecoder()
        a := A{}
        err := decoder.Decode(&a, url.Values{"Array[1234567890]": {"42"}})
        if err != nil {
            log.Fatalln(err)
        }
        for {
        }
    }
    

    The RES usage of this application spikes to 1220MB.

    enhancement 
    opened by justinas 4
  • What about supporting case-insensitive key?

    What about supporting case-insensitive key?

    Package version eg. v9, v10:

    v4

    Issue, Question or Enhancement:

    I want these two requests work at the same time:

    curl host/api?queryTime=timestamp
    curl host/api?querytime=timestamp
    

    In other words, what about supporting case-insensitive key?

    Code sample, to showcase or reproduce:

    type Request struct {
      queryTime string `form:"queryTime"`
    }
    
    var req Request
    decode.Decode(&req, r.Form)
    
    opened by Loyalsoldier 0
  • Multipart form?

    Multipart form?

    Package version eg. v9, v10:

    Issue, Question or Enhancement:

    can you tell me, how can i use this for multipart files??

    Code sample, to showcase or reproduce:

    // Employee
    type Employee struct {
    	Name  string
    	Image *multipart.FileHeader
    }
    
    // Employees
    type Employees struct {
    	Data []Employee
    }
    
    
    {
        "data": [
            {
                "name": "some name1",
                "image": "file1.jpg"
            },
            {
                "name": "some name2",
                "image": "file2.jpg"
            }
        ]
    }
    
    
    opened by tshubham7 1
  • Feature: support

    Feature: support "natural" maps

    It seems that map types are not supported. E.g. map[interface{}]interface{} or map[string]string. Is this the expected behaviour?

    Play

    package main
    
    import (
    	"fmt"
    	"github.com/go-playground/form"
    	"net/url"
    	"reflect"
    )
    
    func main() {
    	dec := form.NewDecoder()
    
    	req := url.Values{"a": []string{"a"}, "b": []string{"b"}, "c": []string{"1"}}
    
    	v := map[interface{}]interface{}{
    		"a": "",
    		"b": "",
    		"c": 0,
    	}
    
    	expected := map[interface{}]interface{}{
    		"a": "a",
    		"b": "b",
    		"c": 1,
    	}
    	if err := dec.Decode(&v, req); err != nil {
    		panic(err)
    	}
    	if !reflect.DeepEqual(v, expected) {
    		fmt.Printf("expected\n %#v\n received\n %#v", expected, v)
    	}
    }
    
    
    opened by mihaiav 0
  • Pointer to int and zero value

    Pointer to int and zero value

    type Request struct {
    	TestInt        *int        `form:"test_int"`
    	TestString  *string   `form:"test_string"`
    }
    

    When providing empty value for "test_string" parameter(r.Form["test_string"]=""), Request.TestString will be not nil and set with the zero value "" as wanted.

    But when "test_int" is provided with an empty string value(r.Form["test_int"]=""), Request.TestInt is still nil and shloud rather be set to the zero value 0.

    It works great with Gorilla Schema

    opened by badoux 6
  • map[string]string encode/decode

    map[string]string encode/decode

    fv, _ := form.NewEncoder().Encode(map[string]string{"a": "b"})
    fmt.Printf(`the str="%s"`+"\n", fv.Encode())
    
    the str="%5Ba%5D=b"
    

    i will httpPost(xxx, encodeIt(x))

    opened by RelicOfTesla 1
  • String array should replace the existing one

    String array should replace the existing one

    Example:

    type Form struct {
       Field []string `form:"field"`
    }
    
    form := Form{ Field: []string{"value1", "value2"} }
    
    // vals is contains 'field': "value3", "value4"
    _ := Decoder.Decode(&form, vals)
    
    // form.Field contains now "value1", "value2", "value3", "value4".
    // Excepted was only "value3", "value4"
    

    If I decode the HTTP post values to this struct, the Field property gets appended by the values in the post data instead of replaced.

    The use case is the following: I pre-fill the Form struct with data based on the DB entity. I use this struct also in the view template to render the values. If I would fill the Form struct after the decoding, it will override all the decoded fields if I not check every single field.

    My logical expectation of the form decoder is:

    • If the form field exists in the values, make sure the value match the decoded value (now it's appending string array, don't tested other kind of arrays/struct array)
    • If not just leave the field how it is (works)
    enhancement question 
    opened by aight8 1
Releases(v4.2.0)
  • v4.2.0(Jul 8, 2021)

    What's new?

    • Add setting use brackets as a namespace separator, thanks @alxfv for the PR
    • Fix panic when we encode uncomparable fields with omitempty tag, thanks @alxfv for the PR
    Source code(tar.gz)
    Source code(zip)
  • v4.1.3(Feb 28, 2021)

  • v4.1.2(Feb 28, 2021)

  • v4.1.1(Nov 17, 2019)

  • v4.1.0(Nov 11, 2019)

  • v4.0.0(Oct 18, 2019)

  • v3.1.4(Feb 3, 2019)

  • v3.1.3(Apr 10, 2018)

    What was fixed?

    Fixed encoder issue when omitempty used in combination with a pointer. see #34 for details, thanks @mifanich for reporting

    Source code(tar.gz)
    Source code(zip)
  • v3.1.2(Apr 8, 2018)

  • v3.1.1(Apr 8, 2018)

    What was fixed?

    in PR #32:

    • Corrected handling of array, not slice, values that can lead to a panic.
    • Rearranged logic to handle multiple values if index and non-index are mixed eg. Value=[]string{"1","2"} Value[2]=[]string{"3"}

    this resolves #29 and #30

    Source code(tar.gz)
    Source code(zip)
  • v3.1.0(Feb 4, 2018)

    What was added

    • Added setting for string form value into interface{} values; previously they were ignored. thanks @Xzya for the issue

    Why only string and not int, float etc...? Because theres no way to tell what type the value should be; just because it CAN be parsed into an int, doesn't mean it should be for your application and so I have left it at setting strings.

    Source code(tar.gz)
    Source code(zip)
  • v3.0.1(Sep 11, 2017)

  • v3.0.0(Jul 31, 2017)

    What's new?

    • Added Embedded struct support
    • Added omitempty just like std lib JSON

    Made a version bump to v3.0.0 because the new Embedded struct logic has the potential to affect existing clients.

    The Encoder has a new option SetAnonymousMode(...) by default it embeds anonymous struct info as if the fields were part of the containing struct itself; to continue to have it split out the Embedded structs just set mode to AnonymousSeparate and it will function exactly as previous versions.

    please see examples detailing new functionality.

    NOTE: if a struct and embedded struct have the same field, this will decode the value into both fields as there is no way to tell which you want; decoding into only the Embedded struct is still supported, again see examples.

    Thanks to @danielchatfield and @michael2m for creating issues to get these features on the radar :+1:

    Source code(tar.gz)
    Source code(zip)
  • v2.3.0(Feb 16, 2017)

    What was added?

    Added a new function to both the Decoder and Encoder called RegisterTagNameFunc.

    NOTES:

    Once a custom function has been registered the default, or custom set, tag name is ignored and relies 100% on the function for the field name data.

    The return value WILL BE CACHED and so return value must be CONSISTENT.

    Source code(tar.gz)
    Source code(zip)
  • v2.2.2(Feb 15, 2017)

    What was fixed?

    • Parsing of struct tag, by name, corrected for when multiple tags exists, this was corrected in #15 thanks @htmd

    P.S. in the future, I will change this so that instead of specifying the tag name, a function will be specified allowing for greater flexibility; but it would be a breaking change so leaving for now until needed.

    Source code(tar.gz)
    Source code(zip)
  • v2.2.1(Feb 13, 2017)

    What was fixed?

    • Added additional notes to RegisterCustomTypeFunc to indicate that if a struct type is registered a url.Value must exist explicitly for the struct and not just the fields.

    eg. url.Values{"User":"Name%3Djoeybloggs"} will call the custom type function with User as the type, however url.Values{"User.Name":"joeybloggs"} will not.

    Fixes #14

    Source code(tar.gz)
    Source code(zip)
  • v2.2.0(Aug 23, 2016)

    What was added?

    Added Mode to both the Encoder and Decoder and can be set with the SetMode(mode) function on either.

    currently there are 2 modes:

    • ModeImplicit - the default mode, looks through all fields to encode or decode values
    • ModeExplicit - looks through only field marked explicitly with the form tag name

    this is for #10 thanks @annismckenzie for the idea

    no breaking changes, just update and enjoy.

    Source code(tar.gz)
    Source code(zip)
  • v2.1.0(Aug 2, 2016)

    What was added?

    • Just some more minor backend performance updates, no changes.
    
    benchmark                                                       old ns/op     new ns/op     delta
    BenchmarkSimpleUserDecodeStruct-8                               318           336           +5.66%
    BenchmarkSimpleUserDecodeStructParallel-8                       95.2          99.5          +4.52%
    BenchmarkSimpleUserEncodeStruct-8                               1000          972           -2.80%
    BenchmarkSimpleUserEncodeStructParallel-8                       325           329           +1.23%
    BenchmarkPrimitivesDecodeStructAllPrimitivesTypes-8             1058          1014          -4.16%
    BenchmarkPrimitivesDecodeStructAllPrimitivesTypesParallel-8     324           294           -9.26%
    BenchmarkPrimitivesEncodeStructAllPrimitivesTypes-8             4823          4799          -0.50%
    BenchmarkPrimitivesEncodeStructAllPrimitivesTypesParallel-8     1732          1581          -8.72%
    BenchmarkComplexArrayDecodeStructAllTypes-8                     16340         16326         -0.09%
    BenchmarkComplexArrayDecodeStructAllTypesParallel-8             5105          4710          -7.74%
    BenchmarkComplexArrayEncodeStructAllTypes-8                     16343         16303         -0.24%
    BenchmarkComplexArrayEncodeStructAllTypesParallel-8             5969          4979          -16.59%
    BenchmarkComplexMapDecodeStructAllTypes-8                       21259         21998         +3.48%
    BenchmarkComplexMapDecodeStructAllTypesParallel-8               7493          6542          -12.69%
    BenchmarkComplexMapEncodeStructAllTypes-8                       17060         17069         +0.05%
    BenchmarkComplexMapEncodeStructAllTypesParallel-8               6421          5609          -12.65%
    BenchmarkDecodeNestedStruct-8                                   3488          3366          -3.50%
    BenchmarkDecodeNestedStructParallel-8                           1203          1096          -8.89%
    BenchmarkEncodeNestedStruct-8                                   2286          2230          -2.45%
    BenchmarkEncodeNestedStructParallel-8                           939           780           -16.93%
    
    benchmark                                                       old allocs     new allocs     delta
    BenchmarkSimpleUserDecodeStruct-8                               1              1              +0.00%
    BenchmarkSimpleUserDecodeStructParallel-8                       1              1              +0.00%
    BenchmarkSimpleUserEncodeStruct-8                               12             11             -8.33%
    BenchmarkSimpleUserEncodeStructParallel-8                       12             11             -8.33%
    BenchmarkPrimitivesDecodeStructAllPrimitivesTypes-8             1              1              +0.00%
    BenchmarkPrimitivesDecodeStructAllPrimitivesTypesParallel-8     1              1              +0.00%
    BenchmarkPrimitivesEncodeStructAllPrimitivesTypes-8             47             46             -2.13%
    BenchmarkPrimitivesEncodeStructAllPrimitivesTypesParallel-8     47             46             -2.13%
    BenchmarkComplexArrayDecodeStructAllTypes-8                     122            121            -0.82%
    BenchmarkComplexArrayDecodeStructAllTypesParallel-8             122            121            -0.82%
    BenchmarkComplexArrayEncodeStructAllTypes-8                     147            146            -0.68%
    BenchmarkComplexArrayEncodeStructAllTypesParallel-8             147            146            -0.68%
    BenchmarkComplexMapDecodeStructAllTypes-8                       131            130            -0.76%
    BenchmarkComplexMapDecodeStructAllTypesParallel-8               131            130            -0.76%
    BenchmarkComplexMapEncodeStructAllTypes-8                       176            175            -0.57%
    BenchmarkComplexMapEncodeStructAllTypesParallel-8               176            175            -0.57%
    BenchmarkDecodeNestedStruct-8                                   15             14             -6.67%
    BenchmarkDecodeNestedStructParallel-8                           15             14             -6.67%
    BenchmarkEncodeNestedStruct-8                                   17             16             -5.88%
    BenchmarkEncodeNestedStructParallel-8                           17             16             -5.88%
    
    benchmark                                                       old bytes     new bytes     delta
    BenchmarkSimpleUserDecodeStruct-8                               64            64            +0.00%
    BenchmarkSimpleUserDecodeStructParallel-8                       64            64            +0.00%
    BenchmarkSimpleUserEncodeStruct-8                               549           485           -11.66%
    BenchmarkSimpleUserEncodeStructParallel-8                       549           485           -11.66%
    BenchmarkPrimitivesDecodeStructAllPrimitivesTypes-8             96            96            +0.00%
    BenchmarkPrimitivesDecodeStructAllPrimitivesTypesParallel-8     96            96            +0.00%
    BenchmarkPrimitivesEncodeStructAllPrimitivesTypes-8             3073          3009          -2.08%
    BenchmarkPrimitivesEncodeStructAllPrimitivesTypesParallel-8     3072          3010          -2.02%
    BenchmarkComplexArrayDecodeStructAllTypes-8                     2289          2257          -1.40%
    BenchmarkComplexArrayDecodeStructAllTypesParallel-8             2291          2257          -1.48%
    BenchmarkComplexArrayEncodeStructAllTypes-8                     7351          7288          -0.86%
    BenchmarkComplexArrayEncodeStructAllTypesParallel-8             7351          7290          -0.83%
    BenchmarkComplexMapDecodeStructAllTypes-8                       5338          5306          -0.60%
    BenchmarkComplexMapDecodeStructAllTypesParallel-8               5342          5308          -0.64%
    BenchmarkComplexMapEncodeStructAllTypes-8                       7161          7100          -0.85%
    BenchmarkComplexMapEncodeStructAllTypesParallel-8               7161          7099          -0.87%
    BenchmarkDecodeNestedStruct-8                                   416           384           -7.69%
    BenchmarkDecodeNestedStructParallel-8                           416           384           -7.69%
    BenchmarkEncodeNestedStruct-8                                   768           704           -8.33%
    BenchmarkEncodeNestedStructParallel-8                           768           704           -8.33%
    
    
    Source code(tar.gz)
    Source code(zip)
  • v2.0.0(Jul 26, 2016)

    What's New in 2.0.0?

    • form now supports Decoding and Encoding of almost any type, not just structs. for #6 eg.
    
    // example url.Values
    values := map[string][]string{ "val1", "val2" }
    
    var arr []string
    
    d.Decode(&arr, values)
    

    Thanks @themihai for suggesting #6 and questioning #7

    Any Fixes?

    • Corrected a bug where when decoding non indexed array values into an array with existing values was overwriting the current values instead of appending to the array, this has been corrected. ( Don't worry too much, most people won't have been using a pre-filled array )
    Source code(tar.gz)
    Source code(zip)
  • v1.10.0(Jul 17, 2016)

    What's New?

    • Nothing just some more backend only performance updates.
    
    benchmark                                                       old ns/op     new ns/op     delta
    BenchmarkSimpleUserDecodeStruct-8                               308           298           -3.25%
    BenchmarkSimpleUserDecodeStructParallel-8                       94.8          91.4          -3.59%
    BenchmarkSimpleUserEncodeStruct-8                               989           966           -2.33%
    BenchmarkSimpleUserEncodeStructParallel-8                       332           313           -5.72%
    BenchmarkPrimitivesDecodeStructAllPrimitivesTypes-8             1004          1010          +0.60%
    BenchmarkPrimitivesDecodeStructAllPrimitivesTypesParallel-8     291           285           -2.06%
    BenchmarkPrimitivesEncodeStructAllPrimitivesTypes-8             4771          4718          -1.11%
    BenchmarkPrimitivesEncodeStructAllPrimitivesTypesParallel-8     1575          1673          +6.22%
    BenchmarkComplexArrayDecodeStructAllTypes-8                     17087         16145         -5.51%
    BenchmarkComplexArrayDecodeStructAllTypesParallel-8             5020          4943          -1.53%
    BenchmarkComplexArrayEncodeStructAllTypes-8                     16219         16020         -1.23%
    BenchmarkComplexArrayEncodeStructAllTypesParallel-8             4961          5129          +3.39%
    BenchmarkComplexMapDecodeStructAllTypes-8                       24898         22933         -7.89%
    BenchmarkComplexMapDecodeStructAllTypesParallel-8               7771          6366          -18.08%
    BenchmarkComplexMapEncodeStructAllTypes-8                       16885         16861         -0.14%
    BenchmarkComplexMapEncodeStructAllTypesParallel-8               5851          5159          -11.83%
    BenchmarkDecodeNestedStruct-8                                   3848          3482          -9.51%
    BenchmarkDecodeNestedStructParallel-8                           1325          1011          -23.70%
    BenchmarkEncodeNestedStruct-8                                   2319          2255          -2.76%
    BenchmarkEncodeNestedStructParallel-8                           874           738           -15.56%
    
    benchmark                                                       old allocs     new allocs     delta
    BenchmarkSimpleUserDecodeStruct-8                               1              1              +0.00%
    BenchmarkSimpleUserDecodeStructParallel-8                       1              1              +0.00%
    BenchmarkSimpleUserEncodeStruct-8                               12             12             +0.00%
    BenchmarkSimpleUserEncodeStructParallel-8                       12             12             +0.00%
    BenchmarkPrimitivesDecodeStructAllPrimitivesTypes-8             1              1              +0.00%
    BenchmarkPrimitivesDecodeStructAllPrimitivesTypesParallel-8     1              1              +0.00%
    BenchmarkPrimitivesEncodeStructAllPrimitivesTypes-8             47             47             +0.00%
    BenchmarkPrimitivesEncodeStructAllPrimitivesTypesParallel-8     47             47             +0.00%
    BenchmarkComplexArrayDecodeStructAllTypes-8                     123            122            -0.81%
    BenchmarkComplexArrayDecodeStructAllTypesParallel-8             123            122            -0.81%
    BenchmarkComplexArrayEncodeStructAllTypes-8                     147            147            +0.00%
    BenchmarkComplexArrayEncodeStructAllTypesParallel-8             147            147            +0.00%
    BenchmarkComplexMapDecodeStructAllTypes-8                       135            131            -2.96%
    BenchmarkComplexMapDecodeStructAllTypesParallel-8               135            131            -2.96%
    BenchmarkComplexMapEncodeStructAllTypes-8                       176            176            +0.00%
    BenchmarkComplexMapEncodeStructAllTypesParallel-8               176            176            +0.00%
    BenchmarkDecodeNestedStruct-8                                   16             15             -6.25%
    BenchmarkDecodeNestedStructParallel-8                           16             15             -6.25%
    BenchmarkEncodeNestedStruct-8                                   17             17             +0.00%
    BenchmarkEncodeNestedStructParallel-8                           17             17             +0.00%
    
    benchmark                                                       old bytes     new bytes     delta
    BenchmarkSimpleUserDecodeStruct-8                               64            64            +0.00%
    BenchmarkSimpleUserDecodeStructParallel-8                       64            64            +0.00%
    BenchmarkSimpleUserEncodeStruct-8                               549           549           +0.00%
    BenchmarkSimpleUserEncodeStructParallel-8                       549           549           +0.00%
    BenchmarkPrimitivesDecodeStructAllPrimitivesTypes-8             96            96            +0.00%
    BenchmarkPrimitivesDecodeStructAllPrimitivesTypesParallel-8     96            96            +0.00%
    BenchmarkPrimitivesEncodeStructAllPrimitivesTypes-8             3073          3073          +0.00%
    BenchmarkPrimitivesEncodeStructAllPrimitivesTypesParallel-8     3073          3072          -0.03%
    BenchmarkComplexArrayDecodeStructAllTypes-8                     2513          2289          -8.91%
    BenchmarkComplexArrayDecodeStructAllTypesParallel-8             2518          2291          -9.02%
    BenchmarkComplexArrayEncodeStructAllTypes-8                     7350          7351          +0.01%
    BenchmarkComplexArrayEncodeStructAllTypesParallel-8             7351          7351          +0.00%
    BenchmarkComplexMapDecodeStructAllTypes-8                       7088          5338          -24.69%
    BenchmarkComplexMapDecodeStructAllTypesParallel-8               7121          5341          -25.00%
    BenchmarkComplexMapEncodeStructAllTypes-8                       7159          7161          +0.03%
    BenchmarkComplexMapEncodeStructAllTypesParallel-8               7161          7160          -0.01%
    BenchmarkDecodeNestedStruct-8                                   640           416           -35.00%
    BenchmarkDecodeNestedStructParallel-8                           640           416           -35.00%
    BenchmarkEncodeNestedStruct-8                                   768           768           +0.00%
    BenchmarkEncodeNestedStructParallel-8                           768           768           +0.00%
    
    
    Source code(tar.gz)
    Source code(zip)
  • v1.9.0(Jul 9, 2016)

    Whats New?

    • Just some more minor backend performance updates inspired by Go 1.7 RC1 changes to the JSON package, parallel performance updated by 10-20% with latest changes.
    
    benchmark                                                       old ns/op     new ns/op     delta
    BenchmarkSimpleUserDecodeStruct-8                               319           308           -3.45%
    BenchmarkSimpleUserDecodeStructParallel-8                       116           94.8          -18.28%
    BenchmarkSimpleUserEncodeStruct-8                               1015          989           -2.56%
    BenchmarkSimpleUserEncodeStructParallel-8                       411           332           -19.22%
    BenchmarkPrimitivesDecodeStructAllPrimitivesTypes-8             1038          1004          -3.28%
    BenchmarkPrimitivesDecodeStructAllPrimitivesTypesParallel-8     368           291           -20.92%
    BenchmarkPrimitivesEncodeStructAllPrimitivesTypes-8             5014          4771          -4.85%
    BenchmarkPrimitivesEncodeStructAllPrimitivesTypesParallel-8     1973          1575          -20.17%
    BenchmarkComplexArrayDecodeStructAllTypes-8                     17656         17087         -3.22%
    BenchmarkComplexArrayDecodeStructAllTypesParallel-8             5801          5020          -13.46%
    BenchmarkComplexArrayEncodeStructAllTypes-8                     16318         16219         -0.61%
    BenchmarkComplexArrayEncodeStructAllTypesParallel-8             5955          4961          -16.69%
    BenchmarkComplexMapDecodeStructAllTypes-8                       25196         24898         -1.18%
    BenchmarkComplexMapDecodeStructAllTypesParallel-8               9443          7771          -17.71%
    BenchmarkComplexMapEncodeStructAllTypes-8                       17061         16885         -1.03%
    BenchmarkComplexMapEncodeStructAllTypesParallel-8               6375          5851          -8.22%
    BenchmarkDecodeNestedStruct-8                                   4102          3848          -6.19%
    BenchmarkDecodeNestedStructParallel-8                           1399          1325          -5.29%
    BenchmarkEncodeNestedStruct-8                                   2440          2319          -4.96%
    BenchmarkEncodeNestedStructParallel-8                           1045          874           -16.36%
    
    benchmark                                                       old allocs     new allocs     delta
    BenchmarkSimpleUserDecodeStruct-8                               1              1              +0.00%
    BenchmarkSimpleUserDecodeStructParallel-8                       1              1              +0.00%
    BenchmarkSimpleUserEncodeStruct-8                               12             12             +0.00%
    BenchmarkSimpleUserEncodeStructParallel-8                       12             12             +0.00%
    BenchmarkPrimitivesDecodeStructAllPrimitivesTypes-8             1              1              +0.00%
    BenchmarkPrimitivesDecodeStructAllPrimitivesTypesParallel-8     1              1              +0.00%
    BenchmarkPrimitivesEncodeStructAllPrimitivesTypes-8             47             47             +0.00%
    BenchmarkPrimitivesEncodeStructAllPrimitivesTypesParallel-8     47             47             +0.00%
    BenchmarkComplexArrayDecodeStructAllTypes-8                     123            123            +0.00%
    BenchmarkComplexArrayDecodeStructAllTypesParallel-8             123            123            +0.00%
    BenchmarkComplexArrayEncodeStructAllTypes-8                     147            147            +0.00%
    BenchmarkComplexArrayEncodeStructAllTypesParallel-8             147            147            +0.00%
    BenchmarkComplexMapDecodeStructAllTypes-8                       135            135            +0.00%
    BenchmarkComplexMapDecodeStructAllTypesParallel-8               135            135            +0.00%
    BenchmarkComplexMapEncodeStructAllTypes-8                       176            176            +0.00%
    BenchmarkComplexMapEncodeStructAllTypesParallel-8               176            176            +0.00%
    BenchmarkDecodeNestedStruct-8                                   16             16             +0.00%
    BenchmarkDecodeNestedStructParallel-8                           16             16             +0.00%
    BenchmarkEncodeNestedStruct-8                                   17             17             +0.00%
    BenchmarkEncodeNestedStructParallel-8                           17             17             +0.00%
    
    benchmark                                                       old bytes     new bytes     delta
    BenchmarkSimpleUserDecodeStruct-8                               64            64            +0.00%
    BenchmarkSimpleUserDecodeStructParallel-8                       64            64            +0.00%
    BenchmarkSimpleUserEncodeStruct-8                               549           549           +0.00%
    BenchmarkSimpleUserEncodeStructParallel-8                       549           549           +0.00%
    BenchmarkPrimitivesDecodeStructAllPrimitivesTypes-8             96            96            +0.00%
    BenchmarkPrimitivesDecodeStructAllPrimitivesTypesParallel-8     96            96            +0.00%
    BenchmarkPrimitivesEncodeStructAllPrimitivesTypes-8             3073          3073          +0.00%
    BenchmarkPrimitivesEncodeStructAllPrimitivesTypesParallel-8     3072          3073          +0.03%
    BenchmarkComplexArrayDecodeStructAllTypes-8                     2515          2513          -0.08%
    BenchmarkComplexArrayDecodeStructAllTypesParallel-8             2518          2518          +0.00%
    BenchmarkComplexArrayEncodeStructAllTypes-8                     7351          7350          -0.01%
    BenchmarkComplexArrayEncodeStructAllTypesParallel-8             7351          7351          +0.00%
    BenchmarkComplexMapDecodeStructAllTypes-8                       7089          7088          -0.01%
    BenchmarkComplexMapDecodeStructAllTypesParallel-8               7123          7121          -0.03%
    BenchmarkComplexMapEncodeStructAllTypes-8                       7162          7159          -0.04%
    BenchmarkComplexMapEncodeStructAllTypesParallel-8               7160          7161          +0.01%
    BenchmarkDecodeNestedStruct-8                                   640           640           +0.00%
    BenchmarkDecodeNestedStructParallel-8                           640           640           +0.00%
    BenchmarkEncodeNestedStruct-8                                   768           768           +0.00%
    BenchmarkEncodeNestedStructParallel-8                           768           768           +0.00%
    
    
    Source code(tar.gz)
    Source code(zip)
  • v1.8.0(Jul 3, 2016)

    What Changed?

    • backend only changes, no breaking changes.
    • fine tuned a few more internals for max performance and decreasing allocations, library is now balanced between primitive and complex struct decoding and encoding with least allocations for both.
    • squashed a potential bug with calculated slice length, upgrading to latest version is recommended
    Source code(tar.gz)
    Source code(zip)
  • v1.7.1(Jun 29, 2016)

    What Changed?

    • Corrected issue where time pointer, *time.Time, was not getting set on the struct field when using built in time parsing. corrected in commit 762ce96aa9e35c0f3e10fe0265e6106e59ff9a03, adding this line was the fix.

    Thanks @bikbah for reporting!

    Source code(tar.gz)
    Source code(zip)
  • v1.7.0(Jun 29, 2016)

    What's New

    Nothing anyone needs to worry about, all backend changes.

    • Minor performance updates, reduced allocations for maps and arrays.
    • Updated Benchmarks
    Source code(tar.gz)
    Source code(zip)
  • v1.6.0(Jun 23, 2016)

  • v1.5.0(Jun 21, 2016)

    What's New?

    • Added Array/Slice global limit size, please refer to #2, reported by @justinas

    by default limit is 10,000 which should suit most peoples needs however if a higher or lower limit is desired/required it can be adjusted with the function SetMaxArraySize(size uint)

    Source code(tar.gz)
    Source code(zip)
  • v1.4.0(Jun 21, 2016)

    What's New?

    Added Encoder to go along with the Decoder.

    example

    Notes

    To maximize compatibility with other systems the Encoder attempts to avoid using array indexes in url.Values if at all possible.

    eg.

    // A struct field of
    Field []string{"1", "2", "3"}
    
    // will be output a url.Value as
    "Field": []string{"1", "2", "3"}
    
    and not
    "Field[0]": []string{"1"}
    "Field[1]": []string{"2"}
    "Field[2]": []string{"3"}
    
    // however there are times where it is unavoidable, like with pointers
    i := int(1)
    Field []*string{nil, nil, &i}
    
    // to avoid index 1 and 2 must use index
    "Field[2]": []string{"1"}
    
    Source code(tar.gz)
    Source code(zip)
  • v1.3.0(Jun 16, 2016)

  • v1.2.1(Jun 14, 2016)

  • v1.2.0(Jun 13, 2016)

Owner
Go Playgound
multiple packages, libraries and programs to further the advancement of Go!
Go Playgound
Go module for encoding structs into URL query parameters

qs Package sonh/qs encodes structs into url.Values. Installation go get github.com/sonh/qs Usage import ( "github.com/sonh/qs" ) Package qs export

Son Huynh 65 Dec 3, 2022
Data validation, cleaning and error collection for golang

GoForms - form data validation, cleaning and error reporting The goforms library is a proof-of-concept for a data validation, cleaning and error colle

Michael Nelson 98 Jan 14, 2022
Go library for parsing and submitting HTML forms

gosubmit Description Docs are available here: https://godoc.org/github.com/jeremija/gosubmit Helps filling out plain html forms during testing. Will a

Jerko Steiner 20 Nov 14, 2022
Package gorilla/securecookie encodes and decodes authenticated and optionally encrypted cookie values for Go web applications.

securecookie securecookie encodes and decodes authenticated and optionally encrypted cookie values. Secure cookies can't be forged, because their valu

Gorilla Web Toolkit 603 Nov 30, 2022
Takes an integer array, returns the array sorted and the number of inversions in the array

Takes an integer slice, returns the slice sorted and the number of inversions in the slice

SaSo 0 Jan 25, 2022
The Dual-Stack Dynamic DNS client, the world's first dynamic DNS client built for IPv6.

dsddns DsDDNS is the Dual-Stack Dynamic DNS client. A dynamic DNS client keeps your DNS records in sync with the IP addresses associated with your hom

Ryan Young 15 Sep 27, 2022
G-array is a GoLang library, that contains the generic function to do the array operations.

G-array Garray is a library written in Go (Golang). Which have a collection of functions to do the array operations. Installation To install G-array p

99x 3 Oct 3, 2022
Grpc-gateway-map-null - gRPC Gateway test using nullable values in map

Demonstrate gRPC gateway behavior with nullable values in maps Using grpc-gatewa

null 1 Jan 6, 2022
Membin is an in-memory database that can be stored on disk. Data model smiliar to key-value but values store as JSON byte array.

Membin Docs | Contributing | License What is Membin? The Membin database system is in-memory database smiliar to key-value databases, target to effici

Membin 3 Jun 3, 2021
:100:Go Struct and Field validation, including Cross Field, Cross Struct, Map, Slice and Array diving

Package validator Package validator implements value validations for structs and individual fields based on tags. It has the following unique features

Go Playgound 11.9k Dec 2, 2022
💯 Go Struct and Field validation, including Cross Field, Cross Struct, Map, Slice and Array diving

Package validator implements value validations for structs and individual fields based on tags.

Flamego 10 Nov 9, 2022
Golang parameter validation, which can replace go-playground/validator, includes ncluding Cross Field, Map, Slice and Array diving, provides readable,flexible, configurable validation.

Checker 中文版本 Checker is a parameter validation package, can be use in struct/non-struct validation, including cross field validation in struct, elemen

Liang Yaopei 78 Sep 26, 2022
💪 Helper Utils For The Go: string, array/slice, map, format, cli, env, filesystem, test and more.

?? Helper Utils For The Go: string, array/slice, map, format, cli, env, filesystem, test and more. Go 的一些工具函数,格式化,特殊处理,常用信息获取等等

Gookit 983 Dec 2, 2022
Convert struct, slice, array, map or others for Golang

XConv zh-CN XConv is a golang type convertor. It convert any value between types (base type, struct, array, slice, map, etc.) Features Convert between

null 18 Aug 16, 2022
TIled map editor CSV export conversion to C array

tiled2c This tool is very simplistic and is a variation of the one written to convert between Tiled map editor CSV exports and a format for the sega s

B1tsh1ft3r 0 Nov 28, 2021
Go library for decoding generic map values into native Go structures and vice versa.

mapstructure mapstructure is a Go library for decoding generic map values to structures and vice versa, while providing helpful error handling. This l

Mitchell Hashimoto 6.4k Dec 2, 2022
Go library for decoding generic map values into native Go structures and vice versa.

mapstructure mapstructure is a Go library for decoding generic map values to structures and vice versa, while providing helpful error handling. This l

Mitchell Hashimoto 6.4k Dec 4, 2022
Go library for encoding native Go structures into generic map values.

wstructs origin: github.com/things-go/structs Go library for encoding native Go structures into generic map values. Installation Use go get. go ge

null 0 Jan 10, 2022
skipmap is a high-performance concurrent sorted map based on skip list. Up to 3x ~ 10x faster than sync.Map in the typical pattern.

Introduction skipmap is a high-performance concurrent map based on skip list. In typical pattern(one million operations, 90%LOAD 9%STORE 1%DELETE), th

ZhangYunHao 102 Dec 2, 2022
Recursively searches a map[string]interface{} structure for another map[string]interface{} structure

msirecurse Recursively searches a map[string]interface{} structure for existence of a map[string]interface{} structure Motivation I wrote this package

Fred Moyer 1 Mar 3, 2022