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 inencoding/json/json.go. Usesprotojsonfor protobuf messages and falls back to the standardencoding/jsonpackage for other types. This serves as the default fallback when no specific content type is specified. - Proto (
proto): Located inencoding/proto/proto.go. The default codec for gRPC transports, handling raw protobuf message marshaling and unmarshaling. - YAML (
yaml): Located inencoding/yaml/yaml.go. Implements serialization viagopkg.in/yaml.v3. - XML (
xml): Located inencoding/xml/xml.go. Uses the standard libraryencoding/xmlpackage. - Form (
x-www-form-urlencoded): Located inencoding/form/form.go. Handlesapplication/x-www-form-urlencodeddata usinggithub.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
Codecinterface withMarshal,Unmarshal, andNamemethods. - Register custom codecs via
encoding.RegisterCodec()inside aninitfunction, 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →