Default Content Encoding Formats in Kratos and How to Add Custom Codecs

Kratos ships with five built-in content encoding formats (JSON, Proto, YAML, XML, and Form) and provides a global registry in encoding/encoding.go that allows developers to register custom codecs by implementing the Codec interface and calling encoding.RegisterCodec() in an init function.

The go-kratos/kratos framework provides a flexible, extensible codec system for HTTP and gRPC transports that maps content subtypes to serialization implementations. Understanding the default content encoding formats supported by Kratos and the registration mechanism enables seamless integration of custom data formats without modifying core library code.

Built-in Content Encoding Formats in Kratos

Kratos registers the following codecs automatically on startup in the global registry located in encoding/encoding.go:

  • JSON (json): Located in encoding/json/json.go. Uses protojson for protobuf messages and falls back to the standard encoding/json package for other types. This serves as the default fallback when no specific content type is specified.
  • Proto (proto): Located in encoding/proto/proto.go. The default codec for gRPC transports, handling raw protobuf message marshaling and unmarshaling.
  • YAML (yaml): Located in encoding/yaml/yaml.go. Implements serialization via gopkg.in/yaml.v3.
  • XML (xml): Located in encoding/xml/xml.go. Uses the standard library encoding/xml package.
  • Form (x-www-form-urlencoded): Located in encoding/form/form.go. Handles application/x-www-form-urlencoded data using github.com/go-playground/form/v4.

Additionally, the MsgPack codec is available as an optional contrib module at contrib/encoding/msgpack/msgpack.go, demonstrating the same registration pattern.

The Codec Interface and Registry Architecture

At the heart of the system is the Codec interface defined in encoding/encoding.go:

type Codec interface {
    Marshal(v any) ([]byte, error)
    Unmarshal(data []byte, v any) error
    Name() string               // the codec name → content‑subtype
}

The global registry maintains a map called registeredCodecs that stores instances indexed by their name. The encoding.RegisterCodec() function adds implementations to this map, making them available for content type negotiation.

How to Register a Custom Codec in Kratos

Follow these steps to add support for proprietary formats like MessagePack, Avro, or custom binary protocols.

1. Implement the Codec Interface

Create a package that fulfills the three required methods:

package mycodec

import "github.com/go-kratos/kratos/v2/encoding"

const Name = "myformat"   // will become the content‑subtype

type codec struct{}

func (c codec) Marshal(v any) ([]byte, error) {
    // convert v → []byte
}

func (c codec) Unmarshal(data []byte, v any) error {
    // fill v from data
}

func (c codec) Name() string { return Name }

2. Register in an Init Function

Add the registration logic to ensure the codec loads automatically:

func init() {
    encoding.RegisterCodec(codec{})
}

3. Import with Blank Identifier

In your service's main.go or initialization code, import the package to trigger the init function:

import _ "path/to/your/module/mycodec"

4. Use via HTTP Headers or Programmatically

Once registered, Kratos automatically negotiates the codec based on headers:

Content-Type: application/myformat
Accept: application/myformat

Or access it directly in code:

c := encoding.GetCodec("myformat")
data, err := c.Marshal(myStruct)

Default Fallback Behavior and Content Negotiation

When processing HTTP requests, Kratos determines the appropriate codec through the CodecForRequest function in transport/http/codec.go (line 35). If the request does not specify a recognized Content-Type or Accept header, the framework defaults to the JSON codec. This ensures that APIs remain functional for clients that omit explicit format headers while still supporting content type negotiation for specialized consumers.

Summary

  • Kratos provides five built-in content encoding formats: JSON, Proto, YAML, XML, and Form, all registered in encoding/encoding.go.
  • The framework uses a global registry (registeredCodecs) mapped by content-subtype strings.
  • Adding custom formats requires implementing the Codec interface with Marshal, Unmarshal, and Name methods.
  • Register custom codecs via encoding.RegisterCodec() inside an init function, then import with a blank identifier.
  • JSON serves as the default fallback when no content type is specified, as implemented in transport/http/codec.go.

Frequently Asked Questions

What is the default content encoding format when a client omits the Content-Type header?

Kratos defaults to JSON encoding when no valid Content-Type or Accept header is present. This behavior is hardcoded in the CodecForRequest function within transport/http/codec.go, which returns the JSON codec as the final fallback option.

Can I override the built-in JSON, Proto, or XML codecs with custom implementations?

Yes. While the built-in codecs register themselves in their respective init functions (e.g., encoding/json/json.go), you can register a codec with the same name string after the default registration to override it. However, this is generally discouraged unless you need to modify serialization behavior globally, as it affects all transports using that content subtype.

How does Kratos handle codec selection for gRPC versus HTTP transports?

For gRPC, the Proto codec is typically selected by default based on the gRPC protocol requirements. For HTTP, Kratos inspects the Content-Type and Accept headers via CodecForRequest in transport/http/codec.go to determine the appropriate codec. Both transports share the same global registry in encoding/encoding.go, so custom codecs work across both protocols automatically.

Where can I find a complete example of a custom codec implementation?

The repository includes a reference implementation in contrib/encoding/msgpack/msgpack.go. This file demonstrates the complete pattern: defining the codec struct, implementing the three interface methods, and registering via encoding.RegisterCodec() in an init function.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →