Skip to main content
Kratos provides a unified encoding system that supports multiple formats including JSON, XML, YAML, Protobuf, and form data. The system is extensible and automatically selects the appropriate codec based on content type.

Codec Interface

encoding/encoding.go:10-19
type Codec interface {
    // Marshal returns the wire format of v
    Marshal(v any) ([]byte, error)
    
    // Unmarshal parses the wire format into v
    Unmarshal(data []byte, v any) error
    
    // Name returns the name of the Codec implementation
    Name() string
}

Supported Formats

JSON

JSON encoding with Protobuf support:
encoding/json/json.go:27-69
import "github.com/go-kratos/kratos/v2/encoding/json"

type User struct {
    ID   int64  `json:"id"`
    Name string `json:"name"`
}

user := &User{ID: 1, Name: "John"}

// Marshal
data, err := json.Marshal(user)
// {"id":1,"name":"John"}

// Unmarshal
var decoded User
err = json.Unmarshal(data, &decoded)
Content-Type: application/json
JSON codec automatically handles both regular structs and Protobuf messages.

XML

XML encoding:
import "github.com/go-kratos/kratos/v2/encoding/xml"

type User struct {
    XMLName xml.Name `xml:"user"`
    ID      int64    `xml:"id"`
    Name    string   `xml:"name"`
}

user := &User{ID: 1, Name: "John"}

// Marshal
data, err := xml.Marshal(user)
// <user><id>1</id><name>John</name></user>

// Unmarshal
var decoded User
err = xml.Unmarshal(data, &decoded)
Content-Type: application/xml, text/xml

YAML

YAML encoding:
import "github.com/go-kratos/kratos/v2/encoding/yaml"

type Config struct {
    Server struct {
        Host string `yaml:"host"`
        Port int    `yaml:"port"`
    } `yaml:"server"`
}

config := &Config{}
config.Server.Host = "localhost"
config.Server.Port = 8000

// Marshal
data, err := yaml.Marshal(config)
// server:
//   host: localhost
//   port: 8000

// Unmarshal
var decoded Config
err = yaml.Unmarshal(data, &decoded)
Content-Type: application/yaml, application/x-yaml

Protobuf

Binary Protobuf encoding:
import "github.com/go-kratos/kratos/v2/encoding/proto"

// Requires Protobuf message
msg := &pb.User{Id: 1, Name: "John"}

// Marshal
data, err := proto.Marshal(msg)

// Unmarshal
var decoded pb.User
err = proto.Unmarshal(data, &decoded)
Content-Type: application/protobuf, application/x-protobuf

Form Data

URL-encoded form data:
encoding/form/form.go:40-88
import "github.com/go-kratos/kratos/v2/encoding/form"

type LoginRequest struct {
    Username string `json:"username"`
    Password string `json:"password"`
    Remember bool   `json:"remember"`
}

req := &LoginRequest{
    Username: "admin",
    Password: "secret",
    Remember: true,
}

// Marshal
data, err := form.Marshal(req)
// username=admin&password=secret&remember=true

// Unmarshal
var decoded LoginRequest
err = form.Unmarshal(data, &decoded)
Content-Type: application/x-www-form-urlencoded
The form codec uses JSON struct tags by default. This can be changed by building with -ldflags="-X github.com/go-kratos/kratos/v2/encoding/form.tagName=form"

Codec Registry

Register Custom Codec

encoding/encoding.go:23-34
import "github.com/go-kratos/kratos/v2/encoding"

type MyCodec struct{}

func (c MyCodec) Marshal(v any) ([]byte, error) {
    // Custom marshaling logic
    return nil, nil
}

func (c MyCodec) Unmarshal(data []byte, v any) error {
    // Custom unmarshaling logic
    return nil
}

func (c MyCodec) Name() string {
    return "mycustom"
}

// Register codec
encoding.RegisterCodec(MyCodec{})

Get Registered Codec

encoding/encoding.go:40-42
import "github.com/go-kratos/kratos/v2/encoding"

// Get codec by name
codec := encoding.GetCodec("json")
if codec != nil {
    data, err := codec.Marshal(value)
}

Automatic Codec Selection

Kratos automatically selects the codec based on Content-Type:

HTTP Server

func handleRequest(ctx http.Context) error {
    var req LoginRequest
    
    // Automatically decodes based on Content-Type header
    if err := ctx.Bind(&req); err != nil {
        return err
    }
    
    // Process request...
    
    // Automatically encodes based on Accept header
    return ctx.Result(200, response)
}
Content-Type Mapping:
  • application/json → JSON codec
  • application/xml → XML codec
  • application/yaml → YAML codec
  • application/protobuf → Protobuf codec
  • application/x-www-form-urlencoded → Form codec

HTTP Client

import "github.com/go-kratos/kratos/v2/transport/http"

client, _ := http.NewClient(
    ctx,
    http.WithEndpoint("127.0.0.1:8000"),
)

var reply Response
err := client.Invoke(
    ctx,
    "POST",
    "/api/login",
    &LoginRequest{Username: "admin"},
    &reply,
    http.ContentType("application/json"), // Specify content type
)

Custom Encoding/Decoding

HTTP Request Encoder

func customEncoder(ctx context.Context, contentType string, in interface{}) ([]byte, error) {
    // Custom encoding logic
    codec := encoding.GetCodec("json")
    return codec.Marshal(in)
}

client, err := http.NewClient(
    ctx,
    http.WithRequestEncoder(customEncoder),
)

HTTP Response Decoder

func customDecoder(ctx context.Context, res *http.Response, out interface{}) error {
    defer res.Body.Close()
    
    data, err := io.ReadAll(res.Body)
    if err != nil {
        return err
    }
    
    // Get codec from response Content-Type
    codec := encoding.GetCodec(httputil.ContentSubtype(res.Header.Get("Content-Type")))
    if codec == nil {
        codec = encoding.GetCodec("json")
    }
    
    return codec.Unmarshal(data, out)
}

client, err := http.NewClient(
    ctx,
    http.WithResponseDecoder(customDecoder),
)

Protobuf Integration

All codecs have special handling for Protobuf messages:

JSON with Protobuf

encoding/json/json.go:34-43
import pb "your-project/api/user/v1"

msg := &pb.User{Id: 1, Name: "John"}

// Automatically uses protojson
data, err := json.Marshal(msg)
// Uses MarshalOptions for Protobuf-friendly JSON

var decoded pb.User
err = json.Unmarshal(data, &decoded)
// Uses UnmarshalOptions
JSON Marshal Options:
MarshalOptions = protojson.MarshalOptions{
    EmitUnpopulated: true,  // Include fields with zero values
}
JSON Unmarshal Options:
UnmarshalOptions = protojson.UnmarshalOptions{
    DiscardUnknown: true,  // Ignore unknown fields
}

Form with Protobuf

encoding/form/form.go:43-47
import pb "your-project/api/user/v1"

msg := &pb.LoginRequest{
    Username: "admin",
    Password: "secret",
}

// Automatically handles Protobuf messages
data, err := form.Marshal(msg)

var decoded pb.LoginRequest
err = form.Unmarshal(data, &decoded)

Best Practices

Let Kratos automatically select the codec based on Content-Type rather than manually choosing.
Design APIs to accept multiple content types for flexibility (JSON, XML, etc.).
Always add JSON tags to structs even if using other formats - they’re used by form codec.
Ensure clients send the correct Content-Type header to get proper encoding/decoding.
Use Protobuf for internal service communication for better performance.
Use JSON for public APIs for better compatibility and debugging.

Format Comparison

FormatSizeSpeedHuman ReadableSchemaUse Case
JSONMediumFastYesOptionalPublic APIs, Web
ProtobufSmallFastestNoRequiredInternal services
XMLLargeSlowYesOptionalLegacy systems
YAMLMediumMediumYesNoConfiguration
FormMediumFastYesNoHTML forms

HTTP Transport

HTTP encoding/decoding

gRPC Transport

Protobuf encoding

Config

Configuration file formats

Errors

Error response encoding

Build docs developers (and LLMs) love