- Docs
- HTTP APIs
- Codec
Codec
Serialize typed values to bytes with composable Encoder and Decoder pairs, JSON by default.
codec turns a typed Go value into bytes and back, so cache, queue, session, and webhook code never hand-roll json.Marshal. Use it with typed wrappers over byte stores, or when defining a wire format for a new adapter. Write a custom codec only when JSON is the wrong format.
Quick start
Section titled “Quick start”codec has no YAML, no env, and no container accessor (there is no c.Codec()). Construct it directly:
package main
import ( "fmt"
"github.com/zenta-dev/zever/shared/codec")
type MyPayload struct { ID string `json:"id"` Name string `json:"name"`}
func main() { c := codec.JSONCodec[MyPayload]{}
data, _ := c.Encode(MyPayload{ID: "u_1", Name: "Ada"}) back, _ := c.Decode(data) fmt.Printf("%s %s\n", back.ID, back.Name)}u_1 AdaJSONCodec[V] is the only implementation Zever ships. Its output is deterministic, so snapshots and exact-byte assertions stay stable. A codec does no I/O and holds no connections, so it is safe to share. The interfaces are Encoder[V] (Encode), Decoder[V] (Decode), and Codec[V] (both); cache.NewTyped applies a Codec[V] to cache Get and Set.
Store typed values in the cache
Section titled “Store typed values in the cache”Resolve the byte store from the container and pass the codec to the typed layer on top:
// imports: config, container, cachememory ("github.com/zenta-dev/zever/adapters/cache/memory"),// "github.com/zenta-dev/zever/core/cache", "github.com/zenta-dev/zever/shared/codec"cachememory.Register()c := container.New(config.Default())inner, _ := c.Cache()typed := cache.NewTyped[string, MyPayload](inner, codec.JSONCodec[MyPayload]{})
typed.Set(ctx, "user:u_1", MyPayload{ID: "u_1", Name: "Ada"}, time.Minute)got, _ := typed.Get(ctx, "user:u_1")fmt.Println(got.Name)AdaUse one Codec[V] per stored type, shared by writer and reader. Queue and session paths follow the same shape: bytes on the wire, typed values in handlers. Resolve those with c.Queue() and c.Session().
Write your own codec
Section titled “Write your own codec”Implement Codec[V] for a binary, compressed, or third-party format:
type gobCodec[V any] struct{}
func (gobCodec[V]) Encode(v V) ([]byte, error) { /* ... */ }func (gobCodec[V]) Decode(data []byte) (V, error) { /* ... */ }
var _ codec.Codec[MyPayload] = gobCodec[MyPayload]{}Keep it symmetric: whatever Encode writes, Decode must read back, including after a version adds a field. JSONCodec ignores unknown fields and defaults missing ones.
Production checklist
Section titled “Production checklist”- Never log encoded bytes at info level. Log IDs and sizes.
- Keep payloads small: IDs and flags in sessions, not full records.
- Use
JSONCodecfor any data you snapshot or hash.
Troubleshooting
Section titled “Troubleshooting”Decode fails after adding a field
Added keys default fine, so the cause is a changed type. Keep JSON types stable or add a versioned wrapper type.
Cache reads return zero values
Writer and reader use different codecs. Build both sides from one Codec[V].
Snapshot tests flap
Use JSONCodec for snapshotted data, or sort keys in Encode.