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
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 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
Content subtype in lowercase (e.g., “json”, “proto”, “xml”)
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
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
}