grpc服务端转换protobuf到http请求参数query
前提
grpc服务接收到request的请求后,需要把参数转换成http,去请求其他接口。
使用go作为grpc的服务端,数据协议是protobuf
想到的几种解决方案:
1.编译好的pb.go文件里有个string(),可以把所有参数都打印出来,参数之间是空格隔开的,参数和值是k:v的形式,但是不带引号,不是json格式
- 2.把接收到的数据转换为json,直接以json的格式,发送请求
3.根据传过来的request反射到固定的struct上,得到具体的属性和获取此属性的方法,再加入到url.values{},再encode()发送请求
实现
方案1
方案1是比较简单的,用空格分割,得到参数和值,再根据":"分割得到参数、值,再加入到url.values{}
代码如下:
param := url.Values{} //得到请求的字符串形式 rs := strings.Split(request.String(), " ") for _, v := range rs { if v != "" { vv := strings.Split(v, ":") param.Add(vv[0], strings.Trim(vv[1], "\"")) vv := strings.SplitN(v, ":", 2) //转换成 val, e := strconv.Unquote(vv[1]) log.Print(val, e) if e == nil { param.Add(vv[0], val) } } }
前期运行OK,后期遇到了两个问题:
- 1.提交的值里有空格时,分割会有问题
- 2.得到的中文是utf8字符
放弃方案1
方案2
把数据先转成json,再解析成map[string]string 的形式,目的是为了省去值都转换为string
str, _ := json.Marshal(request) jsonstr := string(str) m := make(map[string]interface{}) e := json.Unmarshal([]byte(jsonstr), &m) param := url.Values{} if e != nil { return param } for k, v := range m { sv := fmt.Sprint(v) param.Add(k, sv) }
结果:对于中文还有空格的问题是解决了,不过会把int64的数字类型转换成float类型,转换有问题
方案3
根据go的reflect包反射出实际的struct,go编译pb的文件里struct里属性名和proto文件不一样,需要根据属性的tag得到实际的参数名
代码如下:
ty := reflect.TypeOf(request).Elem() #得到struct的属性数量 fieldnum := ty.NumField() #实际数据的指针 ob := reflect.ValueOf(request) param := url.Values{} #由于编译好的属性最后3位不用 for i := 0; i < fieldnum-3; i++ { f := ty.Field(i).Tag.Get("json") fv := strings.Split(f, ",") k := fv[0] fieldname := ty.Field(i).Name ret := ob.MethodByName("Get" + fieldname).Call(nil) if !ret[0].IsZero() { # 这一步,用了很巧的办法把各个类型转换成了string才能加入到param里 v := fmt.Sprint(ret[0]) param.Add(k, v) } } return param
相关推荐
小小书童 2020-05-20
极品小肥羊 2020-04-23
小小书童 2019-12-28
comhaqs 2019-12-28
极品小肥羊 2018-03-17
Erick 2020-11-17
Charlesbases 2020-10-23
Erick 2020-08-21
Erick 2020-06-17
Erick 2020-06-17
mitesi 2020-06-07
Charlesbases 2020-06-07
zagnix 2020-06-04
gumingyaotangwei 2020-05-17
极品小肥羊 2020-04-20
Charlesbases 2020-04-16
mitesi 2020-04-07