You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

70 lines
2.0 KiB

package jsonpb
import (
"bytes"
"fmt"
"io"
"reflect"
"github.com/gogo/protobuf/jsonpb"
"github.com/gogo/protobuf/proto"
gwruntime "github.com/grpc-ecosystem/grpc-gateway/runtime"
jsoniter "github.com/json-iterator/go"
)
var (
typeProtoMessage = reflect.TypeOf((*proto.Message)(nil)).Elem()
json = jsoniter.ConfigCompatibleWithStandardLibrary
)
// JSONPb is a Marshaler which marshals/unmarshals into/from JSON
// with the "github.com/gogo/protobuf/jsonpb".
// It supports fully functionality of protobuf unlike JSONBuiltin.
type JSONPb jsonpb.Marshaler
// ContentType always returns "application/json".
func (*JSONPb) ContentType() string {
return "application/json"
}
// Marshal marshals "v" into JSON
func (j *JSONPb) Marshal(v interface{}) ([]byte, error) {
if pb, ok := v.(proto.Message); ok {
buf, err := json.Marshal(&pb)
if err != nil {
return nil, err
}
return buf, nil
}
return nil, fmt.Errorf("unexpected type %T does not implement %s", v, typeProtoMessage)
}
// Unmarshal unmarshals JSON "data" into "v"
func (j *JSONPb) Unmarshal(data []byte, v interface{}) error {
if pb, ok := v.(proto.Message); ok {
return jsonpb.Unmarshal(bytes.NewReader(data), pb)
}
return fmt.Errorf("unexpected type %T does not implement %s", v, typeProtoMessage)
}
// NewDecoder returns a Decoder which reads JSON stream from "r".
func (j *JSONPb) NewDecoder(r io.Reader) gwruntime.Decoder {
return gwruntime.DecoderFunc(func(v interface{}) error {
if pb, ok := v.(proto.Message); ok {
return jsonpb.Unmarshal(r, pb)
}
return fmt.Errorf("unexpected type %T does not implement %s", v, typeProtoMessage)
})
}
// NewEncoder returns an Encoder which writes JSON stream into "w".
func (j *JSONPb) NewEncoder(w io.Writer) gwruntime.Encoder {
return gwruntime.EncoderFunc(func(v interface{}) error {
if pb, ok := v.(proto.Message); ok {
marshalFn := (*jsonpb.Marshaler)(j).Marshal
return marshalFn(w, pb)
}
return fmt.Errorf("unexpected type %T does not implement %s", v, typeProtoMessage)
})
}