|
我们抽象出了Codec接口,用于统一措置请求的序列化/反序列化逻辑,您也可以实现您本身的Codec以便撑持更多格式。具体源代码在encoding。
目前内置撑持了如下格式:
- form
- json
- protobuf
- xml
- yaml
接口实现
encoding 的 Codec 接口中,包含了 Marshal,Unmarshal,Name 三个方式,用户只需要实现 Codec 即可使用自定义的 encoding。- // Codec 用于定义传输时用到的编码和解码接口,实现这个接口时必需注意,实现必需是线程安全的,可以并发协程调用。
- type Codec interface {
- Marshal(v interface{}) ([]byte, error)
- Unmarshal(data []byte, v interface{}) error
- Name() string
- }
复制代码 实现示例
在实现 Codec 时,可以参考 kratos 的内置实现, 如 json encoding,源代码如下。- // https://github.com/go-kratos/kratos/blob/main/encoding/json/json.go
- package json
- import (
- ”encoding/json”
- ”reflect”
- ”github.com/go-kratos/kratos/v2/encoding”
- ”google.golang.org/protobuf/encoding/protojson”
- ”google.golang.org/protobuf/proto”
- )
- // Name is the name registered for the json codec.
- const Name = ”json”
- var (
- // MarshalOptions is a configurable JSON format marshaller.
- MarshalOptions = protojson.MarshalOptions{
- EmitUnpopulated: true,
- }
- // UnmarshalOptions is a configurable JSON format parser.
- UnmarshalOptions = protojson.UnmarshalOptions{
- DiscardUnknown: true,
- }
- )
- func init() {
- encoding.RegisterCodec(codec{})
- }
- // codec is a Codec implementation with json.
- type codec struct{}
- func (codec) Marshal(v interface{}) ([]byte, error) {
- switch m := v.(type) {
- case json.Marshaler:
- return m.MarshalJSON()
- case proto.Message:
- return MarshalOptions.Marshal(m)
- default:
- return json.Marshal(m)
- }
- }
- func (codec) Unmarshal(data []byte, v interface{}) error {
- switch m := v.(type) {
- case json.Unmarshaler:
- return m.UnmarshalJSON(data)
- case proto.Message:
- return UnmarshalOptions.Unmarshal(data, m)
- default:
- rv := reflect.ValueOf(v)
- for rv := rv; rv.Kind() == reflect.Ptr; {
- if rv.IsNil() {
- rv.Set(reflect.New(rv.Type().Elem()))
- }
- rv = rv.Elem()
- }
- if m, ok := reflect.Indirect(rv).Interface().(proto.Message); ok {
- return UnmarshalOptions.Unmarshal(data, m)
- }
- return json.Unmarshal(data, m)
- }
- }
- func (codec) Name() string {
- return Name
- }
复制代码 使用方式
注册 Codec
- encoding.RegisterCodec(codec{})
复制代码 获取 Codec
- jsonCodec := encoding.GetCodec(”json”)
复制代码 序列化
- // 直接使用内置 Codec 时需要 import _ ”github.com/go-kratos/kratos/v2/encoding/json”
- jsonCodec := encoding.GetCodec(”json”)
- type user struct {
- Name string
- Age string
- state bool
- }
- u := &user{
- Name: ”kratos”,
- Age: ”2”,
- state: false,
- }
- bytes, _ := jsonCodec.Marshal(u)
- fmt.Println(string(bytes))
- // 输出:{”Name”:”kratos”,”Age”:”2”}
复制代码 反序列化
- // 直接使用内置 Codec 时需要 import _ ”github.com/go-kratos/kratos/v2/encoding/json”
- jsonCodec := encoding.GetCodec(”json”)
- type user struct {
- Name string
- Age string
- state bool
- }
- u := &user{}
- jsonCodec.Unmarshal([]byte(`{”Name”:”kratos”,”Age”:”2”}`), &u)
- fmt.Println(*u)
- // 输出:&{kratos 2 false}
复制代码 |
|