serializer API

serializer

package

API reference for the serializer package.

S
struct

sample

pkg/serializer/serializer_test.go:8-12
type sample struct

Fields

Name Type Description
FirstName string json:"first_name"
LastName string json:"last_name"
Age int json:"age"
F
function

TestPolicy_Marshal_SnakeCase

Parameters

pkg/serializer/serializer_test.go:14-27
func TestPolicy_Marshal_SnakeCase(t *testing.T)

{
	p := New(WithNaming(SnakeCase), WithTagName("json"))
	s := sample{FirstName: "John", LastName: "Doe", Age: 30}

	data, err := p.Marshal(s)
	if err != nil {
		t.Fatalf("Marshal failed: %v", err)
	}

	got := string(data)
	if !strings.Contains(got, `"first_name":"John"`) || !strings.Contains(got, `"last_name":"Doe"`) || !strings.Contains(got, `"age":30`) {
		t.Errorf("Marshal: got %q", got)
	}
}
F
function

TestPolicy_Unmarshal_SnakeCase

Parameters

pkg/serializer/serializer_test.go:29-44
func TestPolicy_Unmarshal_SnakeCase(t *testing.T)

{
	p := New(WithNaming(SnakeCase), WithTagName("json"))
	data := []byte(`{"first_name":"Jane","last_name":"Smith","age":25}`)

	var s sample
	if err := p.Unmarshal(data, &s); err != nil {
		t.Fatalf("Unmarshal failed: %v", err)
	}

	if s.FirstName != "Jane" {
		t.Errorf("FirstName: got %q, want %q", s.FirstName, "Jane")
	}
	if s.Age != 25 {
		t.Errorf("Age: got %d, want %d", s.Age, 25)
	}
}
F
function

TestPolicy_IgnoreNil

Parameters

pkg/serializer/serializer_test.go:46-61
func TestPolicy_IgnoreNil(t *testing.T)

{
	p := New(WithIgnoreNil(), WithTagName("json"))
	type withPtr struct {
		Name  string  `json:"name"`
		Score *int    `json:"score"`
	}
	s := withPtr{Name: "test", Score: nil}
	data, err := p.Marshal(s)
	if err != nil {
		t.Fatalf("Marshal failed: %v", err)
	}
	got := string(data)
	if got != `{"name":"test"}` {
		t.Errorf("Marshal with IgnoreNil: got %q", got)
	}
}
F
function

TestPolicy_IgnoreZero

Parameters

pkg/serializer/serializer_test.go:63-78
func TestPolicy_IgnoreZero(t *testing.T)

{
	p := New(WithIgnoreZero(), WithTagName("json"))
	type withZero struct {
		Name string `json:"name"`
		Age  int    `json:"age"`
	}
	s := withZero{Name: "test", Age: 0}
	data, err := p.Marshal(s)
	if err != nil {
		t.Fatalf("Marshal failed: %v", err)
	}
	got := string(data)
	if got != `{"name":"test"}` {
		t.Errorf("Marshal with IgnoreZero: got %q", got)
	}
}
F
function

TestPolicy_CamelCase

Parameters

pkg/serializer/serializer_test.go:80-95
func TestPolicy_CamelCase(t *testing.T)

{
	p := New(WithNaming(CamelCase), WithTagName("json"))
	type camel struct {
		FirstName string
		LastName  string
	}
	s := camel{FirstName: "A", LastName: "B"}
	data, err := p.Marshal(s)
	if err != nil {
		t.Fatalf("Marshal failed: %v", err)
	}
	got := string(data)
	if got != `{"firstName":"A","lastName":"B"}` {
		t.Errorf("Marshal CamelCase: got %q", got)
	}
}
T
type

NamingStrategy

NamingStrategy controls how struct field names are transformed during serialization.

pkg/serializer/serializer.go:11-11
type NamingStrategy int
T
type

ConverterFactory

ConverterFactory creates a custom type converter for serialization.

pkg/serializer/serializer.go:23-23
type ConverterFactory func() Converter
I
interface

Converter

Converter handles custom type serialization.

pkg/serializer/serializer.go:26-29
type Converter interface

Methods

Encode
Method

Parameters

v any

Returns

any
error
func Encode(...)
Decode
Method

Parameters

v any

Returns

error
func Decode(...)
S
struct

Policy

Policy defines serialization behavior including naming and custom type handling.

pkg/serializer/serializer.go:32-39
type Policy struct

Methods

Marshal
Method

Marshal serializes v to JSON bytes using the policy.

Parameters

v any

Returns

[]byte
error
func (*Policy) Marshal(v any) ([]byte, error)
{
	data, err := p.toMap(v)
	if err != nil {
		return nil, err
	}
	return json.Marshal(data)
}
Unmarshal
Method

Unmarshal deserializes JSON bytes into v using the policy.

Parameters

data []byte
v any

Returns

error
func (*Policy) Unmarshal(data []byte, v any) error
{
	var raw map[string]any
	if err := json.Unmarshal(data, &raw); err != nil {
		return err
	}
	return p.fromMap(raw, v)
}

MarshalToString serializes v to a JSON string.

Parameters

v any

Returns

string
error
func (*Policy) MarshalToString(v any) (string, error)
{
	data, err := p.Marshal(v)
	if err != nil {
		return "", err
	}
	return string(data), nil
}
toMap
Method

Parameters

v any

Returns

map[string]any
error
func (*Policy) toMap(v any) (map[string]any, error)
{
	rv := reflect.ValueOf(v)
	if rv.Kind() == reflect.Ptr {
		rv = rv.Elem()
	}
	if rv.Kind() != reflect.Struct {
		result := make(map[string]any)
		result["value"] = v
		return result, nil
	}

	rt := rv.Type()
	result := make(map[string]any)

	for i := 0; i < rt.NumField(); i++ {
		field := rt.Field(i)
		if !field.IsExported() {
			continue
		}

		fv := rv.Field(i)

		if p.ignoreNil && fv.Kind() == reflect.Ptr && fv.IsNil() {
			continue
		}
		if p.ignoreZero && fv.IsZero() {
			continue
		}

		name := p.fieldName(field)
		result[name] = fv.Interface()
	}
	return result, nil
}
fromMap
Method

Parameters

raw map[string]any
v any

Returns

error
func (*Policy) fromMap(raw map[string]any, v any) error
{
	rv := reflect.ValueOf(v)
	if rv.Kind() != reflect.Ptr || rv.Elem().Kind() != reflect.Struct {
		return json.Unmarshal(mustJSON(raw), v)
	}

	elem := rv.Elem()
	rt := elem.Type()

	for i := 0; i < rt.NumField(); i++ {
		field := rt.Field(i)
		if !field.IsExported() {
			continue
		}

		name := p.fieldName(field)
		if val, ok := raw[name]; ok {
			fv := elem.Field(i)
			if fv.CanSet() {
				setValue(fv, val)
			}
		}
	}
	return nil
}
fieldName
Method

Parameters

Returns

string
func (*Policy) fieldName(field reflect.StructField) string
{
	if tag := field.Tag.Get(p.tagName); tag != "" {
		parts := strings.Split(tag, ",")
		if parts[0] != "" {
			return parts[0]
		}
	}
	return transformName(field.Name, p.naming)
}

Fields

Name Type Description
naming NamingStrategy
ignoreNil bool
ignoreZero bool
customTypes map[reflect.Type]ConverterFactory
tagName string
mu sync.RWMutex
T
type

Option

Option configures a Policy.

pkg/serializer/serializer.go:42-42
type Option func(*Policy)
F
function

New

New creates a Policy with the given options.

Parameters

opts
...Option

Returns

pkg/serializer/serializer.go:45-55
func New(opts ...Option) *Policy

{
	p := &Policy{
		naming:      PascalCase,
		tagName:     "json",
		customTypes: make(map[reflect.Type]ConverterFactory),
	}
	for _, opt := range opts {
		opt(p)
	}
	return p
}
F
function

WithNaming

WithNaming sets the naming strategy.

Parameters

Returns

pkg/serializer/serializer.go:58-60
func WithNaming(n NamingStrategy) Option

{
	return func(p *Policy) { p.naming = n }
}
F
function

WithIgnoreNil

WithIgnoreNil skips nil pointers during marshaling.

Returns

pkg/serializer/serializer.go:63-65
func WithIgnoreNil() Option

{
	return func(p *Policy) { p.ignoreNil = true }
}
F
function

WithIgnoreZero

WithIgnoreZero skips zero values during marshaling.

Returns

pkg/serializer/serializer.go:68-70
func WithIgnoreZero() Option

{
	return func(p *Policy) { p.ignoreZero = true }
}
F
function

WithTagName

WithTagName sets the struct tag used for field names (default: “json”).

Parameters

tag
string

Returns

pkg/serializer/serializer.go:73-75
func WithTagName(tag string) Option

{
	return func(p *Policy) { p.tagName = tag }
}
F
function

WithCustomType

WithCustomType registers a custom converter for a specific type.

Parameters

Returns

pkg/serializer/serializer.go:78-80
func WithCustomType(typ reflect.Type, factory ConverterFactory) Option

{
	return func(p *Policy) { p.customTypes[typ] = factory }
}
F
function

transformName

Parameters

name
string
strategy

Returns

string
pkg/serializer/serializer.go:180-189
func transformName(name string, strategy NamingStrategy) string

{
	switch strategy {
	case SnakeCase:
		return toSnake(name)
	case CamelCase:
		return toCamel(name)
	default:
		return name
	}
}
F
function

toSnake

Parameters

s
string

Returns

string
pkg/serializer/serializer.go:191-200
func toSnake(s string) string

{
	var result strings.Builder
	for i, r := range s {
		if i > 0 && r >= 'A' && r <= 'Z' {
			result.WriteByte('_')
		}
		result.WriteRune(r)
	}
	return strings.ToLower(result.String())
}
F
function

toCamel

Parameters

s
string

Returns

string
pkg/serializer/serializer.go:202-207
func toCamel(s string) string

{
	if len(s) == 0 {
		return s
	}
	return strings.ToLower(s[:1]) + s[1:]
}
F
function

setValue

Parameters

val
any
pkg/serializer/serializer.go:209-217
func setValue(fv reflect.Value, val any)

{
	if val == nil {
		return
	}
	rv := reflect.ValueOf(val)
	if rv.Type().ConvertibleTo(fv.Type()) {
		fv.Set(rv.Convert(fv.Type()))
	}
}
F
function

mustJSON

Parameters

v
any

Returns

[]byte
pkg/serializer/serializer.go:219-222
func mustJSON(v any) []byte

{
	data, _ := json.Marshal(v)
	return data
}