marshal_jsonpb.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. package runtime
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "io"
  7. "reflect"
  8. "github.com/golang/protobuf/jsonpb"
  9. "github.com/golang/protobuf/proto"
  10. )
  11. // JSONPb is a Marshaler which marshals/unmarshals into/from JSON
  12. // with the "github.com/golang/protobuf/jsonpb".
  13. // It supports fully functionality of protobuf unlike JSONBuiltin.
  14. //
  15. // The NewDecoder method returns a DecoderWrapper, so the underlying
  16. // *json.Decoder methods can be used.
  17. type JSONPb jsonpb.Marshaler
  18. // ContentType always returns "application/json".
  19. func (*JSONPb) ContentType() string {
  20. return "application/json"
  21. }
  22. // Marshal marshals "v" into JSON.
  23. func (j *JSONPb) Marshal(v interface{}) ([]byte, error) {
  24. if _, ok := v.(proto.Message); !ok {
  25. return j.marshalNonProtoField(v)
  26. }
  27. var buf bytes.Buffer
  28. if err := j.marshalTo(&buf, v); err != nil {
  29. return nil, err
  30. }
  31. return buf.Bytes(), nil
  32. }
  33. func (j *JSONPb) marshalTo(w io.Writer, v interface{}) error {
  34. p, ok := v.(proto.Message)
  35. if !ok {
  36. buf, err := j.marshalNonProtoField(v)
  37. if err != nil {
  38. return err
  39. }
  40. _, err = w.Write(buf)
  41. return err
  42. }
  43. return (*jsonpb.Marshaler)(j).Marshal(w, p)
  44. }
  45. // marshalNonProto marshals a non-message field of a protobuf message.
  46. // This function does not correctly marshals arbitrary data structure into JSON,
  47. // but it is only capable of marshaling non-message field values of protobuf,
  48. // i.e. primitive types, enums; pointers to primitives or enums; maps from
  49. // integer/string types to primitives/enums/pointers to messages.
  50. func (j *JSONPb) marshalNonProtoField(v interface{}) ([]byte, error) {
  51. if v == nil {
  52. return []byte("null"), nil
  53. }
  54. rv := reflect.ValueOf(v)
  55. for rv.Kind() == reflect.Ptr {
  56. if rv.IsNil() {
  57. return []byte("null"), nil
  58. }
  59. rv = rv.Elem()
  60. }
  61. if rv.Kind() == reflect.Map {
  62. m := make(map[string]*json.RawMessage)
  63. for _, k := range rv.MapKeys() {
  64. buf, err := j.Marshal(rv.MapIndex(k).Interface())
  65. if err != nil {
  66. return nil, err
  67. }
  68. m[fmt.Sprintf("%v", k.Interface())] = (*json.RawMessage)(&buf)
  69. }
  70. if j.Indent != "" {
  71. return json.MarshalIndent(m, "", j.Indent)
  72. }
  73. return json.Marshal(m)
  74. }
  75. if enum, ok := rv.Interface().(protoEnum); ok && !j.EnumsAsInts {
  76. return json.Marshal(enum.String())
  77. }
  78. return json.Marshal(rv.Interface())
  79. }
  80. // Unmarshal unmarshals JSON "data" into "v"
  81. func (j *JSONPb) Unmarshal(data []byte, v interface{}) error {
  82. return unmarshalJSONPb(data, v)
  83. }
  84. // NewDecoder returns a Decoder which reads JSON stream from "r".
  85. func (j *JSONPb) NewDecoder(r io.Reader) Decoder {
  86. d := json.NewDecoder(r)
  87. return DecoderWrapper{Decoder: d}
  88. }
  89. // DecoderWrapper is a wrapper around a *json.Decoder that adds
  90. // support for protos to the Decode method.
  91. type DecoderWrapper struct {
  92. *json.Decoder
  93. }
  94. // Decode wraps the embedded decoder's Decode method to support
  95. // protos using a jsonpb.Unmarshaler.
  96. func (d DecoderWrapper) Decode(v interface{}) error {
  97. return decodeJSONPb(d.Decoder, v)
  98. }
  99. // NewEncoder returns an Encoder which writes JSON stream into "w".
  100. func (j *JSONPb) NewEncoder(w io.Writer) Encoder {
  101. return EncoderFunc(func(v interface{}) error { return j.marshalTo(w, v) })
  102. }
  103. func unmarshalJSONPb(data []byte, v interface{}) error {
  104. d := json.NewDecoder(bytes.NewReader(data))
  105. return decodeJSONPb(d, v)
  106. }
  107. func decodeJSONPb(d *json.Decoder, v interface{}) error {
  108. p, ok := v.(proto.Message)
  109. if !ok {
  110. return decodeNonProtoField(d, v)
  111. }
  112. unmarshaler := &jsonpb.Unmarshaler{AllowUnknownFields: true}
  113. return unmarshaler.UnmarshalNext(d, p)
  114. }
  115. func decodeNonProtoField(d *json.Decoder, v interface{}) error {
  116. rv := reflect.ValueOf(v)
  117. if rv.Kind() != reflect.Ptr {
  118. return fmt.Errorf("%T is not a pointer", v)
  119. }
  120. for rv.Kind() == reflect.Ptr {
  121. if rv.IsNil() {
  122. rv.Set(reflect.New(rv.Type().Elem()))
  123. }
  124. if rv.Type().ConvertibleTo(typeProtoMessage) {
  125. unmarshaler := &jsonpb.Unmarshaler{AllowUnknownFields: true}
  126. return unmarshaler.UnmarshalNext(d, rv.Interface().(proto.Message))
  127. }
  128. rv = rv.Elem()
  129. }
  130. if rv.Kind() == reflect.Map {
  131. if rv.IsNil() {
  132. rv.Set(reflect.MakeMap(rv.Type()))
  133. }
  134. conv, ok := convFromType[rv.Type().Key().Kind()]
  135. if !ok {
  136. return fmt.Errorf("unsupported type of map field key: %v", rv.Type().Key())
  137. }
  138. m := make(map[string]*json.RawMessage)
  139. if err := d.Decode(&m); err != nil {
  140. return err
  141. }
  142. for k, v := range m {
  143. result := conv.Call([]reflect.Value{reflect.ValueOf(k)})
  144. if err := result[1].Interface(); err != nil {
  145. return err.(error)
  146. }
  147. bk := result[0]
  148. bv := reflect.New(rv.Type().Elem())
  149. if err := unmarshalJSONPb([]byte(*v), bv.Interface()); err != nil {
  150. return err
  151. }
  152. rv.SetMapIndex(bk, bv.Elem())
  153. }
  154. return nil
  155. }
  156. if _, ok := rv.Interface().(protoEnum); ok {
  157. var repr interface{}
  158. if err := d.Decode(&repr); err != nil {
  159. return err
  160. }
  161. switch repr.(type) {
  162. case string:
  163. // TODO(yugui) Should use proto.StructProperties?
  164. return fmt.Errorf("unmarshaling of symbolic enum %q not supported: %T", repr, rv.Interface())
  165. case float64:
  166. rv.Set(reflect.ValueOf(int32(repr.(float64))).Convert(rv.Type()))
  167. return nil
  168. default:
  169. return fmt.Errorf("cannot assign %#v into Go type %T", repr, rv.Interface())
  170. }
  171. }
  172. return d.Decode(v)
  173. }
  174. type protoEnum interface {
  175. fmt.Stringer
  176. EnumDescriptor() ([]byte, []int)
  177. }
  178. var typeProtoMessage = reflect.TypeOf((*proto.Message)(nil)).Elem()
  179. // Delimiter for newline encoded JSON streams.
  180. func (j *JSONPb) Delimiter() []byte {
  181. return []byte("\n")
  182. }