0Pricing
Go Academy · Lesson

Practical Reflection: Serializers

Building a simple JSON-like serializer with reflect

Practical Reflection: Serializers is a free Go Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Go Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Custom JSON serializer overview

Building a custom serializer with reflection demonstrates practical reflection: iterate struct fields, read tags, access values, and build output — the same approach used by encoding/json internally.

Simple struct-to-map

Convert a struct to a map[string]any using reflection:

func StructToMap(v any) map[string]any {
    t := reflect.TypeOf(v)
    val := reflect.ValueOf(v)
    result := make(map[string]any, t.NumField())
    for i := 0; i < t.NumField(); i++ {
        f := t.Field(i)
        if !f.IsExported() { continue }
        key := f.Tag.Get("json")
        if key == "" { key = f.Name }
        result[key] = val.Field(i).Interface()
    }
    return result
}

Handling pointers

Dereference pointer fields before reading their values:

fv := val.Field(i)
if fv.Kind() == reflect.Ptr {
    if fv.IsNil() { continue }
    fv = fv.Elem()
}

Handling nested structs

Recursively process nested struct fields:

if fv.Kind() == reflect.Struct {
    result[key] = StructToMap(fv.Interface())
    continue
}

omitempty support

Skip zero-value fields if the tag includes "omitempty":

if strings.Contains(tag, "omitempty") && fv.IsZero() { continue }

Map-to-struct (deserializer)

Populate a struct from a map by matching map keys to field tags:

func MapToStruct(m map[string]any, dest any) {
    t := reflect.TypeOf(dest).Elem()
    v := reflect.ValueOf(dest).Elem()
    for i := 0; i < t.NumField(); i++ {
        key := t.Field(i).Tag.Get("json")
        if val, ok := m[key]; ok {
            v.Field(i).Set(reflect.ValueOf(val))
        }
    }
}

Type coercion

Map values from JSON are often float64 for numbers. Coerce them to the target field type when setting:

if f.Type.Kind() == reflect.Int && reflect.TypeOf(val).Kind() == reflect.Float64 {
    v.Field(i).SetInt(int64(val.(float64)))
}

Caching field metadata

Cache the field-to-tag mapping in a sync.Map keyed by reflect.Type to avoid repeated reflection on every serialization call.

Code generation alternative

For performance-critical paths, generate type-specific serialisers with tools like easyjson or ffjson. They avoid runtime reflection entirely.

When to build custom serializers

Custom serializers are useful for: non-JSON formats (BSON, Avro, CSV), custom encoding rules, or tight performance requirements. For most use cases, encoding/json is sufficient.

Testing the serializer

Round-trip test: serialize a struct to map, deserialize back, assert the values match the original:

u := User{Name: "Alice", Age: 30}
m := StructToMap(u)
var u2 User
MapToStruct(m, &u2)
assert.Equal(t, u, u2)

Quick Check

Why is field metadata caching important when building a reflection-based serializer?

Recap: Reflection-Based Serializers

Key points:

  • Iterate fields with NumField/Field; read tags with Tag.Get
  • Handle pointers, nested structs, and zero values
  • Cache field metadata in sync.Map for performance
  • Use code generation for highest throughput

Frequently asked questions

Is the “Practical Reflection: Serializers” lesson free?

Yes — the full text of “Practical Reflection: Serializers” is free to read here on the web, and the Go Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Go Academy course, upgrade to CoddyKit PRO.

What will I learn in “Practical Reflection: Serializers”?

Building a simple JSON-like serializer with reflect You practise Go Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Go Academy?

No prior experience is required. Go Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Practical Reflection: Serializers” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Go Academy lesson?

Yes. Every Go Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. reflect.Type and reflect.Value
  2. Inspecting Struct Fields and Tags
  3. Dynamic Function Calls
  4. Practical Reflection: Serializers
← Back to Go Academy