JU
JustBeYou/serialize
Serialize any Go struct with no additional effort.
Serialize
serialize should be used to easily define serializable structs for your already existing data structures,
everything in native Go.
Table of contents
Motivation
- Using Protobuf, FlatBuffers or other related tools are hard to set up or
imply using a separate domain specific language (DSL) - Using JSON or XML is not storage efficient
- Most of the existing solutions do not support Go polymorphism (using
interface{}) - There is little flexibility when it comes to treating different fields
in a different manner (for example, when serializing for hashing you would
like to exclude the hash field itself) - The standard way of serializing structures in Go is
gob, but it is
unintuitive to use and not suitable for processes like hashing (the output
is very environment dependent)
Features
- Serialize primitive types, user defined structures and arrays
- Serialize polymorphic fields (ie.
interface{}) - Options for each struct field
- Multiple serializers interfaces with different options
- Runtime information kept only about
interface{}fields, structure schema is kept directly in code
Example
This is a short example of serialize's main features.
package main
import "fmt"
//go:generate serialize -file=$GOFILE -type=Foo -serializer=hashing
type Foo struct {
Value int
Hash string `hashing:"ignore"` // This means that the "HashingSerializer" will ignore this field
Custom Bar
Poly interface{}
}
//go:generate serialize -file=$GOFILE -type=Bar -serializer=hashing
type Bar struct {
Value int
}
// This table declaration is needed only if you use interface{} fields in your structs
//go:generate serialize -file=$GOFILE -table=true
var TypeIdTable = map[string]uint16{
"Foo": 1,
"Bar": 2,
}
func main() {
foo := Foo{0, "this will be the hash", Bar{0}, Bar{1}}
// Default serializer
output, _ := foo.Serialize()
unserializedData, consumedBytes, _ := Foo{}.Unserialize(output)
newFoo := unserializedData.(Foo)
fmt.Printf("%v -> %v -> %v (%d bytes)\n", foo, output, newFoo, consumedBytes)
// Custom serializer that ignores the Hash field
output, _ = foo.HashingSerialize()
unserializedData, consumedBytes, _ = Foo{}.HashingUnserialize(output)
newFoo = unserializedData.(Foo)
fmt.Printf("%v -> %v -> %v (%d bytes)\n", foo, output, newFoo, consumedBytes)
}
// Interfaces for our custom serializer
type HashingSerializer interface {
HashingSerialize() ([]byte, error)
}
type HashingUnserializer interface {
HashingUnserialize([]byte) (interface{}, uint64, error)
}To do's
- Support
map - Support arrays of
interface{} - Benchmarks for time/memory
- Better flow for polymorphism handling
Contributing & feedback
If you find this library useful and you would like to share some thoughts or help developing it, drop me an email at
mihailferaru2000@gmail.com
And don't forget to STAR it! ๐