GitHunt
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

  1. Motivation
  2. Features
  3. Example
  4. To do's
  5. Contributing & feedback

Motivation

  1. Using Protobuf, FlatBuffers or other related tools are hard to set up or
    imply using a separate domain specific language (DSL)
  2. Using JSON or XML is not storage efficient
  3. Most of the existing solutions do not support Go polymorphism (using
    interface{})
  4. 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)
  5. 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

  1. Serialize primitive types, user defined structures and arrays
  2. Serialize polymorphic fields (ie. interface{})
  3. Options for each struct field
  4. Multiple serializers interfaces with different options
  5. 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

  1. Support map
  2. Support arrays of interface{}
  3. Benchmarks for time/memory
  4. 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! ๐ŸŒŸ

Languages

Go96.9%Python3.1%

Contributors

Created June 25, 2020
Updated March 14, 2026
JustBeYou/serialize | GitHunt