trpc.group/trpc-go/trpc-go@v1.0.3/restful/serialize_form.go (about) 1 // 2 // 3 // Tencent is pleased to support the open source community by making tRPC available. 4 // 5 // Copyright (C) 2023 THL A29 Limited, a Tencent company. 6 // All rights reserved. 7 // 8 // If you have downloaded a copy of the tRPC source code from Tencent, 9 // please note that tRPC source code is licensed under the Apache 2.0 License, 10 // A copy of the Apache 2.0 License is included in this file. 11 // 12 // 13 14 package restful 15 16 import ( 17 "errors" 18 "net/url" 19 "strings" 20 21 "google.golang.org/protobuf/proto" 22 ) 23 24 func init() { 25 RegisterSerializer(&FormSerializer{}) 26 } 27 28 // FormSerializer is used for Content-Type: application/x-www-form-urlencoded. 29 type FormSerializer struct { 30 // If DiscardUnknown is set, unknown fields are ignored. 31 DiscardUnknown bool 32 } 33 34 // Marshal implements Serializer. 35 // It does the same thing as the jsonpb marshaler's Marshal method. 36 func (*FormSerializer) Marshal(v interface{}) ([]byte, error) { 37 msg, ok := v.(proto.Message) 38 if !ok { // marshal a field of tRPC message 39 return marshal(v) 40 } 41 // marshal tRPC message 42 return Marshaller.Marshal(msg) 43 } 44 45 // Unmarshal implements Serializer 46 func (f *FormSerializer) Unmarshal(data []byte, v interface{}) error { 47 msg, ok := assertProtoMessage(v) 48 if !ok { 49 return errNotProtoMessageType 50 } 51 52 // get url.Values 53 vs, err := url.ParseQuery(string(data)) 54 if err != nil { 55 return err 56 } 57 // populate proto message 58 for key, values := range vs { 59 fieldPath := strings.Split(key, ".") 60 if err := PopulateMessage(msg, fieldPath, values); err != nil { 61 if !f.DiscardUnknown || !errors.Is(err, ErrTraverseNotFound) { 62 return err 63 } 64 } 65 } 66 67 return nil 68 } 69 70 // Name implements Serializer. 71 func (*FormSerializer) Name() string { 72 return "application/x-www-form-urlencoded" 73 } 74 75 // ContentType implements Serializer. 76 // Does the same thing as jsonpb marshaler. 77 func (*FormSerializer) ContentType() string { 78 return "application/json" 79 }