10 "github.com/golang/protobuf/jsonpb"
11 "github.com/golang/protobuf/proto"
14 // JSONPb is a Marshaler which marshals/unmarshals into/from JSON
15 // with the "github.com/golang/protobuf/jsonpb".
16 // It supports fully functionality of protobuf unlike JSONBuiltin.
18 // The NewDecoder method returns a DecoderWrapper, so the underlying
19 // *json.Decoder methods can be used.
20 type JSONPb jsonpb.Marshaler
22 // ContentType always returns "application/json".
23 func (*JSONPb) ContentType() string {
24 return "application/json"
27 // Marshal marshals "v" into JSON.
28 func (j *JSONPb) Marshal(v interface{}) ([]byte, error) {
29 if _, ok := v.(proto.Message); !ok {
30 return j.marshalNonProtoField(v)
34 if err := j.marshalTo(&buf, v); err != nil {
37 return buf.Bytes(), nil
40 func (j *JSONPb) marshalTo(w io.Writer, v interface{}) error {
41 p, ok := v.(proto.Message)
43 buf, err := j.marshalNonProtoField(v)
50 return (*jsonpb.Marshaler)(j).Marshal(w, p)
54 // protoMessageType is stored to prevent constant lookup of the same type at runtime.
55 protoMessageType = reflect.TypeOf((*proto.Message)(nil)).Elem()
58 // marshalNonProto marshals a non-message field of a protobuf message.
59 // This function does not correctly marshals arbitrary data structure into JSON,
60 // but it is only capable of marshaling non-message field values of protobuf,
61 // i.e. primitive types, enums; pointers to primitives or enums; maps from
62 // integer/string types to primitives/enums/pointers to messages.
63 func (j *JSONPb) marshalNonProtoField(v interface{}) ([]byte, error) {
65 return []byte("null"), nil
67 rv := reflect.ValueOf(v)
68 for rv.Kind() == reflect.Ptr {
70 return []byte("null"), nil
75 if rv.Kind() == reflect.Slice {
78 return []byte("[]"), nil
80 return []byte("null"), nil
83 if rv.Type().Elem().Implements(protoMessageType) {
85 err := buf.WriteByte('[')
89 for i := 0; i < rv.Len(); i++ {
91 err = buf.WriteByte(',')
96 if err = (*jsonpb.Marshaler)(j).Marshal(&buf, rv.Index(i).Interface().(proto.Message)); err != nil {
100 err = buf.WriteByte(']')
105 return buf.Bytes(), nil
109 if rv.Kind() == reflect.Map {
110 m := make(map[string]*json.RawMessage)
111 for _, k := range rv.MapKeys() {
112 buf, err := j.Marshal(rv.MapIndex(k).Interface())
116 m[fmt.Sprintf("%v", k.Interface())] = (*json.RawMessage)(&buf)
119 return json.MarshalIndent(m, "", j.Indent)
121 return json.Marshal(m)
123 if enum, ok := rv.Interface().(protoEnum); ok && !j.EnumsAsInts {
124 return json.Marshal(enum.String())
126 return json.Marshal(rv.Interface())
129 // Unmarshal unmarshals JSON "data" into "v"
130 func (j *JSONPb) Unmarshal(data []byte, v interface{}) error {
131 return unmarshalJSONPb(data, v)
134 // NewDecoder returns a Decoder which reads JSON stream from "r".
135 func (j *JSONPb) NewDecoder(r io.Reader) Decoder {
136 d := json.NewDecoder(r)
137 return DecoderWrapper{Decoder: d}
140 // DecoderWrapper is a wrapper around a *json.Decoder that adds
141 // support for protos to the Decode method.
142 type DecoderWrapper struct {
146 // Decode wraps the embedded decoder's Decode method to support
147 // protos using a jsonpb.Unmarshaler.
148 func (d DecoderWrapper) Decode(v interface{}) error {
149 return decodeJSONPb(d.Decoder, v)
152 // NewEncoder returns an Encoder which writes JSON stream into "w".
153 func (j *JSONPb) NewEncoder(w io.Writer) Encoder {
154 return EncoderFunc(func(v interface{}) error { return j.marshalTo(w, v) })
157 func unmarshalJSONPb(data []byte, v interface{}) error {
158 d := json.NewDecoder(bytes.NewReader(data))
159 return decodeJSONPb(d, v)
162 func decodeJSONPb(d *json.Decoder, v interface{}) error {
163 p, ok := v.(proto.Message)
165 return decodeNonProtoField(d, v)
167 unmarshaler := &jsonpb.Unmarshaler{AllowUnknownFields: true}
168 return unmarshaler.UnmarshalNext(d, p)
171 func decodeNonProtoField(d *json.Decoder, v interface{}) error {
172 rv := reflect.ValueOf(v)
173 if rv.Kind() != reflect.Ptr {
174 return fmt.Errorf("%T is not a pointer", v)
176 for rv.Kind() == reflect.Ptr {
178 rv.Set(reflect.New(rv.Type().Elem()))
180 if rv.Type().ConvertibleTo(typeProtoMessage) {
181 unmarshaler := &jsonpb.Unmarshaler{AllowUnknownFields: true}
182 return unmarshaler.UnmarshalNext(d, rv.Interface().(proto.Message))
186 if rv.Kind() == reflect.Map {
188 rv.Set(reflect.MakeMap(rv.Type()))
190 conv, ok := convFromType[rv.Type().Key().Kind()]
192 return fmt.Errorf("unsupported type of map field key: %v", rv.Type().Key())
195 m := make(map[string]*json.RawMessage)
196 if err := d.Decode(&m); err != nil {
199 for k, v := range m {
200 result := conv.Call([]reflect.Value{reflect.ValueOf(k)})
201 if err := result[1].Interface(); err != nil {
205 bv := reflect.New(rv.Type().Elem())
206 if err := unmarshalJSONPb([]byte(*v), bv.Interface()); err != nil {
209 rv.SetMapIndex(bk, bv.Elem())
213 if _, ok := rv.Interface().(protoEnum); ok {
215 if err := d.Decode(&repr); err != nil {
220 // TODO(yugui) Should use proto.StructProperties?
221 return fmt.Errorf("unmarshaling of symbolic enum %q not supported: %T", repr, rv.Interface())
223 rv.Set(reflect.ValueOf(int32(repr.(float64))).Convert(rv.Type()))
226 return fmt.Errorf("cannot assign %#v into Go type %T", repr, rv.Interface())
232 type protoEnum interface {
234 EnumDescriptor() ([]byte, []int)
237 var typeProtoMessage = reflect.TypeOf((*proto.Message)(nil)).Elem()
239 // Delimiter for newline encoded JSON streams.
240 func (j *JSONPb) Delimiter() []byte {