base-golang/pkg/websocket/codec/json/json.go
2024-07-23 10:23:43 +08:00

98 lines
2.1 KiB
Go

package json
import (
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"git.bvbej.com/bvbej/base-golang/pkg/websocket/codec"
)
type jsonCodec struct{}
type jsonReq struct {
Router string `json:"router"`
Data []byte `json:"data"`
Error string `json:"error,omitempty"`
}
type jsonAck struct {
Router string `json:"router"`
Data string `json:"data"`
Error string `json:"error,omitempty"`
}
func init() {
codec.RegisterCodec("json_codec", new(jsonCodec))
}
func (*jsonCodec) Marshal(router string, dataPtr any, retErr error) ([]byte, error) {
if router == "" {
return nil, fmt.Errorf("marshal: router is empty")
}
if dataPtr == nil && retErr == nil {
return nil, fmt.Errorf("marshal data in package is nil. router:%s dt:%T", router, dataPtr)
}
ack := &jsonAck{
Router: router,
}
if dataPtr != nil {
data, err := json.Marshal(dataPtr)
if err != nil {
return nil, fmt.Errorf("marshal json marshal failed. routerr:%s dt:%T err:%v", router, dataPtr, err)
}
ack.Data = base64.StdEncoding.EncodeToString(data)
}
if retErr != nil {
ack.Error = retErr.Error()
}
ackByte, err := json.Marshal(ack)
if err != nil {
return nil, fmt.Errorf("marshal json marshal failed. routerr:%s dt:%T err:%v", router, dataPtr, err)
}
return ackByte, nil
}
func (*jsonCodec) Unmarshal(msg []byte) (int, *codec.MsgPack, error) {
var i = len(msg)
req := &jsonReq{}
err := json.Unmarshal(msg, req)
if err != nil {
return i, nil, errors.New("unmarshal split message id failed")
}
var router = req.Router
msgPack := &codec.MsgPack{Router: router}
dt := codec.GetMessage(router)
if dt == nil {
return i, nil, fmt.Errorf("unmarshal message not registed. router:%s", router)
}
if req.Data != nil {
err = json.Unmarshal(req.Data, dt)
if err != nil {
return i, nil, fmt.Errorf("unmarshal json unmarshal failed. dt:%T msg:%s err:%v", dt, string(msg), err)
}
}
msgPack.DataPtr = dt
if req.Error != "" {
msgPack.Err = errors.New(req.Error)
}
return i, msgPack, nil
}
func (*jsonCodec) ToString(data any) string {
ab, err := json.Marshal(data)
if err != nil {
return fmt.Sprintf("invalid type %T", data)
}
return string(ab)
}