Skip to main content
The Encoding API provides a pluggable codec system for marshaling and unmarshaling data in various formats.

Interfaces

Codec

Defines the interface for encoding and decoding messages.
type Codec interface {
    Marshal(v any) ([]byte, error)
    Unmarshal(data []byte, v any) error
    Name() string
}
Marshal
func(v any) ([]byte, error)
Marshals the value v into wire format bytes
Unmarshal
func(data []byte, v any) error
Unmarshals wire format bytes into value v
Name
func() string
Returns the codec name (used in content type). Must be static and lowercase.

Functions

RegisterCodec

Registers a codec for use with all transport clients and servers.
func RegisterCodec(codec Codec)
codec
Codec
Codec to register. Must not be nil and must have a non-empty name.
Example:
import "github.com/go-kratos/kratos/v2/encoding"

type myCodec struct{}

func (c *myCodec) Marshal(v any) ([]byte, error) {
    // Custom marshal implementation
    return nil, nil
}

func (c *myCodec) Unmarshal(data []byte, v any) error {
    // Custom unmarshal implementation
    return nil
}

func (c *myCodec) Name() string {
    return "custom"
}

func init() {
    encoding.RegisterCodec(&myCodec{})
}

GetCodec

Retrieves a registered codec by content subtype.
func GetCodec(contentSubtype string) Codec
contentSubtype
string
Content subtype in lowercase (e.g., “json”, “proto”, “xml”)
codec
Codec
The registered codec, or nil if not found
Example:
codec := encoding.GetCodec("json")
if codec != nil {
    data, err := codec.Marshal(myStruct)
}

Built-in Codecs

Kratos includes several built-in codecs that are automatically registered:

JSON

import _ "github.com/go-kratos/kratos/v2/encoding/json"
  • Name: "json"
  • Content-Type: application/json
  • Based on standard encoding/json

Protocol Buffers

import _ "github.com/go-kratos/kratos/v2/encoding/proto"
  • Name: "proto"
  • Content-Type: application/x-protobuf
  • Based on google.golang.org/protobuf

XML

import _ "github.com/go-kratos/kratos/v2/encoding/xml"
  • Name: "xml"
  • Content-Type: application/xml
  • Based on standard encoding/xml

YAML

import _ "github.com/go-kratos/kratos/v2/encoding/yaml"
  • Name: "yaml"
  • Content-Type: application/x-yaml
  • Based on gopkg.in/yaml.v3

Form

import _ "github.com/go-kratos/kratos/v2/encoding/form"
  • Name: "form"
  • Content-Type: application/x-www-form-urlencoded
  • For HTML form encoding

Usage Examples

Using Built-in Codecs

package main

import (
    "fmt"
    "github.com/go-kratos/kratos/v2/encoding"
    _ "github.com/go-kratos/kratos/v2/encoding/json"
)

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

func main() {
    codec := encoding.GetCodec("json")
    
    user := &User{ID: 1, Name: "John"}
    
    // Marshal
    data, err := codec.Marshal(user)
    if err != nil {
        panic(err)
    }
    fmt.Printf("JSON: %s\n", data)
    
    // Unmarshal
    var decoded User
    err = codec.Unmarshal(data, &decoded)
    if err != nil {
        panic(err)
    }
    fmt.Printf("User: %+v\n", decoded)
}

Custom Codec Implementation

package main

import (
    "encoding/base64"
    "encoding/json"
    "github.com/go-kratos/kratos/v2/encoding"
)

// Base64JSONCodec encodes JSON and wraps it in base64
type Base64JSONCodec struct{}

func (c *Base64JSONCodec) Marshal(v any) ([]byte, error) {
    jsonData, err := json.Marshal(v)
    if err != nil {
        return nil, err
    }
    
    encoded := base64.StdEncoding.EncodeToString(jsonData)
    return []byte(encoded), nil
}

func (c *Base64JSONCodec) Unmarshal(data []byte, v any) error {
    decoded, err := base64.StdEncoding.DecodeString(string(data))
    if err != nil {
        return err
    }
    
    return json.Unmarshal(decoded, v)
}

func (c *Base64JSONCodec) Name() string {
    return "base64json"
}

func init() {
    encoding.RegisterCodec(&Base64JSONCodec{})
}

Content Type Negotiation

package main

import (
    "strings"
    "github.com/go-kratos/kratos/v2/encoding"
)

func getCodecFromContentType(contentType string) encoding.Codec {
    // Extract subtype from content type
    // e.g., "application/json" -> "json"
    parts := strings.Split(contentType, "/")
    if len(parts) != 2 {
        return nil
    }
    
    subtype := strings.TrimSpace(parts[1])
    // Remove charset and other parameters
    subtype = strings.Split(subtype, ";")[0]
    
    return encoding.GetCodec(subtype)
}

// Usage
func handleRequest(contentType string, data []byte) {
    codec := getCodecFromContentType(contentType)
    if codec == nil {
        // Handle unsupported content type
        return
    }
    
    var payload interface{}
    err := codec.Unmarshal(data, &payload)
    // ...
}

Dynamic Codec Selection

func encodeResponse(data interface{}, format string) ([]byte, error) {
    codec := encoding.GetCodec(format)
    if codec == nil {
        // Fallback to JSON
        codec = encoding.GetCodec("json")
    }
    
    return codec.Marshal(data)
}

// Usage
responseJSON, _ := encodeResponse(user, "json")
responseXML, _ := encodeResponse(user, "xml")
responseYAML, _ := encodeResponse(user, "yaml")

HTTP Server with Content Negotiation

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

func NewHTTPServer() *http.Server {
    srv := http.NewServer(
        http.ResponseEncoder(func(w http.ResponseWriter, r *http.Request, v interface{}) error {
            // Get Accept header
            accept := r.Header.Get("Accept")
            
            // Determine codec from Accept header
            var codecName string
            switch {
            case strings.Contains(accept, "application/json"):
                codecName = "json"
            case strings.Contains(accept, "application/xml"):
                codecName = "xml"
            case strings.Contains(accept, "application/x-protobuf"):
                codecName = "proto"
            default:
                codecName = "json" // default
            }
            
            codec := encoding.GetCodec(codecName)
            data, err := codec.Marshal(v)
            if err != nil {
                return err
            }
            
            w.Header().Set("Content-Type", "application/"+codecName)
            _, err = w.Write(data)
            return err
        }),
    )
    return srv
}

Build docs developers (and LLMs) love