Protobuf3使用MessageToJson序列化时如何避免int64被转为字符串
解决方案
方案1:直接使用官方内置参数(推荐)
Protobuf 3.18.0及以上版本的MessageToJson接口已原生支持64位整数输出为数字类型,只需新增use_integers_for_64bit_types=True参数即可满足需求,同时可以保留你设置的默认字段导出逻辑。
示例代码如下:
from google.protobuf.json_format import MessageToJson data = MessageToJson( proto_obj, including_default_value_fields=True, use_integers_for_64bit_types=True )
注意:如果生成的JSON需要传递给前端JavaScript使用请做好校验,JavaScript的Number类型最大安全整数为
2^53-1,超过该范围的int64值会出现精度丢失,如果你的业务场景中int64取值不会超出该范围可以放心使用该方案。
方案2:兼容旧版本Protobuf的手动处理方案
如果你的Protobuf版本低于3.18.0,没有上述内置参数,可以先将proto对象转为Python字典,手动转换所有int64类型字段后再序列化JSON,示例代码如下:
import json from google.protobuf.json_format import MessageToDict from google.protobuf.descriptor import FieldDescriptor # 先导出为字典,保留默认值 proto_dict = MessageToDict( proto_obj, including_default_value_fields=True ) # 递归转换所有64位整数字段为int类型 def cast_int64_fields(descriptor, message_dict): for field in descriptor.fields: # 匹配所有64位整数类型 if field.type in [ FieldDescriptor.TYPE_INT64, FieldDescriptor.TYPE_UINT64, FieldDescriptor.TYPE_SINT64, FieldDescriptor.TYPE_FIXED64, FieldDescriptor.TYPE_SFIXED64 ]: if field.label == FieldDescriptor.LABEL_REPEATED: message_dict[field.name] = [int(v) for v in message_dict[field.name]] else: message_dict[field.name] = int(message_dict[field.name]) # 递归处理嵌套消息 elif field.type == FieldDescriptor.TYPE_MESSAGE and field.name in message_dict: if field.label == FieldDescriptor.LABEL_REPEATED: for sub_msg in message_dict[field.name]: cast_int64_fields(field.message_type, sub_msg) else: cast_int64_fields(field.message_type, message_dict[field.name]) return message_dict # 处理字段类型后序列化JSON processed_dict = cast_int64_fields(proto_obj.DESCRIPTOR, proto_dict) data = json.dumps(processed_dict)
内容的提问来源于stack exchange,提问作者Zar Ashouri
相关产品推荐
相关产品推荐

