github.com/grpc-ecosystem/grpc-gateway/v2@v2.19.1/runtime/marshal_jsonpb.go (about) 1 package runtime 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "io" 8 "reflect" 9 "strconv" 10 11 "google.golang.org/protobuf/encoding/protojson" 12 "google.golang.org/protobuf/proto" 13 ) 14 15 // JSONPb is a Marshaler which marshals/unmarshals into/from JSON 16 // with the "google.golang.org/protobuf/encoding/protojson" marshaler. 17 // It supports the full functionality of protobuf unlike JSONBuiltin. 18 // 19 // The NewDecoder method returns a DecoderWrapper, so the underlying 20 // *json.Decoder methods can be used. 21 type JSONPb struct { 22 protojson.MarshalOptions 23 protojson.UnmarshalOptions 24 } 25 26 // ContentType always returns "application/json". 27 func (*JSONPb) ContentType(_ interface{}) string { 28 return "application/json" 29 } 30 31 // Marshal marshals "v" into JSON. 32 func (j *JSONPb) Marshal(v interface{}) ([]byte, error) { 33 if _, ok := v.(proto.Message); !ok { 34 return j.marshalNonProtoField(v) 35 } 36 37 var buf bytes.Buffer 38 if err := j.marshalTo(&buf, v); err != nil { 39 return nil, err 40 } 41 return buf.Bytes(), nil 42 } 43 44 func (j *JSONPb) marshalTo(w io.Writer, v interface{}) error { 45 p, ok := v.(proto.Message) 46 if !ok { 47 buf, err := j.marshalNonProtoField(v) 48 if err != nil { 49 return err 50 } 51 _, err = w.Write(buf) 52 return err 53 } 54 b, err := j.MarshalOptions.Marshal(p) 55 if err != nil { 56 return err 57 } 58 59 _, err = w.Write(b) 60 return err 61 } 62 63 var ( 64 // protoMessageType is stored to prevent constant lookup of the same type at runtime. 65 protoMessageType = reflect.TypeOf((*proto.Message)(nil)).Elem() 66 ) 67 68 // marshalNonProto marshals a non-message field of a protobuf message. 69 // This function does not correctly marshal arbitrary data structures into JSON, 70 // it is only capable of marshaling non-message field values of protobuf, 71 // i.e. primitive types, enums; pointers to primitives or enums; maps from 72 // integer/string types to primitives/enums/pointers to messages. 73 func (j *JSONPb) marshalNonProtoField(v interface{}) ([]byte, error) { 74 if v == nil { 75 return []byte("null"), nil 76 } 77 rv := reflect.ValueOf(v) 78 for rv.Kind() == reflect.Ptr { 79 if rv.IsNil() { 80 return []byte("null"), nil 81 } 82 rv = rv.Elem() 83 } 84 85 if rv.Kind() == reflect.Slice { 86 if rv.IsNil() { 87 if j.EmitUnpopulated { 88 return []byte("[]"), nil 89 } 90 return []byte("null"), nil 91 } 92 93 if rv.Type().Elem().Implements(protoMessageType) { 94 var buf bytes.Buffer 95 if err := buf.WriteByte('['); err != nil { 96 return nil, err 97 } 98 for i := 0; i < rv.Len(); i++ { 99 if i != 0 { 100 if err := buf.WriteByte(','); err != nil { 101 return nil, err 102 } 103 } 104 if err := j.marshalTo(&buf, rv.Index(i).Interface().(proto.Message)); err != nil { 105 return nil, err 106 } 107 } 108 if err := buf.WriteByte(']'); err != nil { 109 return nil, err 110 } 111 112 return buf.Bytes(), nil 113 } 114 115 if rv.Type().Elem().Implements(typeProtoEnum) { 116 var buf bytes.Buffer 117 if err := buf.WriteByte('['); err != nil { 118 return nil, err 119 } 120 for i := 0; i < rv.Len(); i++ { 121 if i != 0 { 122 if err := buf.WriteByte(','); err != nil { 123 return nil, err 124 } 125 } 126 var err error 127 if j.UseEnumNumbers { 128 _, err = buf.WriteString(strconv.FormatInt(rv.Index(i).Int(), 10)) 129 } else { 130 _, err = buf.WriteString("\"" + rv.Index(i).Interface().(protoEnum).String() + "\"") 131 } 132 if err != nil { 133 return nil, err 134 } 135 } 136 if err := buf.WriteByte(']'); err != nil { 137 return nil, err 138 } 139 140 return buf.Bytes(), nil 141 } 142 } 143 144 if rv.Kind() == reflect.Map { 145 m := make(map[string]*json.RawMessage) 146 for _, k := range rv.MapKeys() { 147 buf, err := j.Marshal(rv.MapIndex(k).Interface()) 148 if err != nil { 149 return nil, err 150 } 151 m[fmt.Sprintf("%v", k.Interface())] = (*json.RawMessage)(&buf) 152 } 153 if j.Indent != "" { 154 return json.MarshalIndent(m, "", j.Indent) 155 } 156 return json.Marshal(m) 157 } 158 if enum, ok := rv.Interface().(protoEnum); ok && !j.UseEnumNumbers { 159 return json.Marshal(enum.String()) 160 } 161 return json.Marshal(rv.Interface()) 162 } 163 164 // Unmarshal unmarshals JSON "data" into "v" 165 func (j *JSONPb) Unmarshal(data []byte, v interface{}) error { 166 return unmarshalJSONPb(data, j.UnmarshalOptions, v) 167 } 168 169 // NewDecoder returns a Decoder which reads JSON stream from "r". 170 func (j *JSONPb) NewDecoder(r io.Reader) Decoder { 171 d := json.NewDecoder(r) 172 return DecoderWrapper{ 173 Decoder: d, 174 UnmarshalOptions: j.UnmarshalOptions, 175 } 176 } 177 178 // DecoderWrapper is a wrapper around a *json.Decoder that adds 179 // support for protos to the Decode method. 180 type DecoderWrapper struct { 181 *json.Decoder 182 protojson.UnmarshalOptions 183 } 184 185 // Decode wraps the embedded decoder's Decode method to support 186 // protos using a jsonpb.Unmarshaler. 187 func (d DecoderWrapper) Decode(v interface{}) error { 188 return decodeJSONPb(d.Decoder, d.UnmarshalOptions, v) 189 } 190 191 // NewEncoder returns an Encoder which writes JSON stream into "w". 192 func (j *JSONPb) NewEncoder(w io.Writer) Encoder { 193 return EncoderFunc(func(v interface{}) error { 194 if err := j.marshalTo(w, v); err != nil { 195 return err 196 } 197 // mimic json.Encoder by adding a newline (makes output 198 // easier to read when it contains multiple encoded items) 199 _, err := w.Write(j.Delimiter()) 200 return err 201 }) 202 } 203 204 func unmarshalJSONPb(data []byte, unmarshaler protojson.UnmarshalOptions, v interface{}) error { 205 d := json.NewDecoder(bytes.NewReader(data)) 206 return decodeJSONPb(d, unmarshaler, v) 207 } 208 209 func decodeJSONPb(d *json.Decoder, unmarshaler protojson.UnmarshalOptions, v interface{}) error { 210 p, ok := v.(proto.Message) 211 if !ok { 212 return decodeNonProtoField(d, unmarshaler, v) 213 } 214 215 // Decode into bytes for marshalling 216 var b json.RawMessage 217 if err := d.Decode(&b); err != nil { 218 return err 219 } 220 221 return unmarshaler.Unmarshal([]byte(b), p) 222 } 223 224 func decodeNonProtoField(d *json.Decoder, unmarshaler protojson.UnmarshalOptions, v interface{}) error { 225 rv := reflect.ValueOf(v) 226 if rv.Kind() != reflect.Ptr { 227 return fmt.Errorf("%T is not a pointer", v) 228 } 229 for rv.Kind() == reflect.Ptr { 230 if rv.IsNil() { 231 rv.Set(reflect.New(rv.Type().Elem())) 232 } 233 if rv.Type().ConvertibleTo(typeProtoMessage) { 234 // Decode into bytes for marshalling 235 var b json.RawMessage 236 if err := d.Decode(&b); err != nil { 237 return err 238 } 239 240 return unmarshaler.Unmarshal([]byte(b), rv.Interface().(proto.Message)) 241 } 242 rv = rv.Elem() 243 } 244 if rv.Kind() == reflect.Map { 245 if rv.IsNil() { 246 rv.Set(reflect.MakeMap(rv.Type())) 247 } 248 conv, ok := convFromType[rv.Type().Key().Kind()] 249 if !ok { 250 return fmt.Errorf("unsupported type of map field key: %v", rv.Type().Key()) 251 } 252 253 m := make(map[string]*json.RawMessage) 254 if err := d.Decode(&m); err != nil { 255 return err 256 } 257 for k, v := range m { 258 result := conv.Call([]reflect.Value{reflect.ValueOf(k)}) 259 if err := result[1].Interface(); err != nil { 260 return err.(error) 261 } 262 bk := result[0] 263 bv := reflect.New(rv.Type().Elem()) 264 if v == nil { 265 null := json.RawMessage("null") 266 v = &null 267 } 268 if err := unmarshalJSONPb([]byte(*v), unmarshaler, bv.Interface()); err != nil { 269 return err 270 } 271 rv.SetMapIndex(bk, bv.Elem()) 272 } 273 return nil 274 } 275 if rv.Kind() == reflect.Slice { 276 if rv.Type().Elem().Kind() == reflect.Uint8 { 277 var sl []byte 278 if err := d.Decode(&sl); err != nil { 279 return err 280 } 281 if sl != nil { 282 rv.SetBytes(sl) 283 } 284 return nil 285 } 286 287 var sl []json.RawMessage 288 if err := d.Decode(&sl); err != nil { 289 return err 290 } 291 if sl != nil { 292 rv.Set(reflect.MakeSlice(rv.Type(), 0, 0)) 293 } 294 for _, item := range sl { 295 bv := reflect.New(rv.Type().Elem()) 296 if err := unmarshalJSONPb([]byte(item), unmarshaler, bv.Interface()); err != nil { 297 return err 298 } 299 rv.Set(reflect.Append(rv, bv.Elem())) 300 } 301 return nil 302 } 303 if _, ok := rv.Interface().(protoEnum); ok { 304 var repr interface{} 305 if err := d.Decode(&repr); err != nil { 306 return err 307 } 308 switch v := repr.(type) { 309 case string: 310 // TODO(yugui) Should use proto.StructProperties? 311 return fmt.Errorf("unmarshaling of symbolic enum %q not supported: %T", repr, rv.Interface()) 312 case float64: 313 rv.Set(reflect.ValueOf(int32(v)).Convert(rv.Type())) 314 return nil 315 default: 316 return fmt.Errorf("cannot assign %#v into Go type %T", repr, rv.Interface()) 317 } 318 } 319 return d.Decode(v) 320 } 321 322 type protoEnum interface { 323 fmt.Stringer 324 EnumDescriptor() ([]byte, []int) 325 } 326 327 var typeProtoEnum = reflect.TypeOf((*protoEnum)(nil)).Elem() 328 329 var typeProtoMessage = reflect.TypeOf((*proto.Message)(nil)).Elem() 330 331 // Delimiter for newline encoded JSON streams. 332 func (j *JSONPb) Delimiter() []byte { 333 return []byte("\n") 334 } 335 336 var ( 337 convFromType = map[reflect.Kind]reflect.Value{ 338 reflect.String: reflect.ValueOf(String), 339 reflect.Bool: reflect.ValueOf(Bool), 340 reflect.Float64: reflect.ValueOf(Float64), 341 reflect.Float32: reflect.ValueOf(Float32), 342 reflect.Int64: reflect.ValueOf(Int64), 343 reflect.Int32: reflect.ValueOf(Int32), 344 reflect.Uint64: reflect.ValueOf(Uint64), 345 reflect.Uint32: reflect.ValueOf(Uint32), 346 reflect.Slice: reflect.ValueOf(Bytes), 347 } 348 )