Python3 gRPC服务返回float类型0.0值时响应为空问题
问题根因
这是Protobuf 3(proto3)默认序列化规则导致的正常现象,不属于服务逻辑或代码生成bug:
- proto3为压缩传输体积,序列化消息时,所有值等于该类型默认值的字段都会被直接省略,不会写入二进制传输流
- 基础数值类型
float的默认值为0.0,因此返回的similarity值为0.0时,该字段会在序列化阶段被过滤,通过JSON转码工具、接口调试工具看到的响应就会是空对象{} - 该过滤行为仅发生在序列化输出环节,实际gRPC客户端按proto定义反序列化响应时,会自动给缺失字段赋对应类型的默认值,直接读取
response.similarity依然能拿到正确的0.0值,不会影响正常RPC调用的数值传递。
解决方案
根据业务场景选择其中一种即可:
- 方案1:如果只是调试时需要在JSON输出中看到默认值字段,在使用protobuf官方库做JSON转码时,开启包含默认值的参数即可:
from google.protobuf import json_format # 原写法:json_format.MessageToJson(resp) # 修改为: resp_json = json_format.MessageToJson(resp, including_default_value_fields=True) - 方案2:如果业务上需要区分「未返回相似度」和「相似度为0」两种语义,把基础float类型换成protobuf官方提供的包装类型。包装类型是Message类型,默认值为
None,只要显式赋值0.0就会被正常序列化:
首先修改.proto文件,导入包装类型定义:
重新生成py代码后,赋值时需要显式构造包装类型对象:syntax = "proto3"; package utils; import "google/protobuf/wrappers.proto"; service Utils { rpc TextSimilarity (TextSimilarityUtilsRequest) returns (TextSimilarityUtilsResponse); } message TextSimilarityUtilsRequest { string source1 = 1; string source2 = 2; } message TextSimilarityUtilsResponse { google.protobuf.FloatValue similarity = 1; }# 相似度为0.0时的返回写法 from google.protobuf import wrappers_pb2 return TextSimilarityUtilsResponse(similarity=wrappers_pb2.FloatValue(value=0.0)) - 方案3:如果没有特殊的JSON输出要求、也不需要区分零值和未赋值状态,完全可以不用修改任何代码,客户端侧直接读取字段值就能拿到正确的0.0,空对象只是序列化展示层面的效果,不影响实际RPC功能。
内容的提问来源于stack exchange,提问作者Endurance
相关产品推荐
相关产品推荐

