如何避免Protobuf json_format将Python字典中的int转为float?
解决Protobuf Struct转换时整数自动转浮点数的问题
问题原因
Protobuf的struct_pb2.Struct是为兼容JSON数据结构设计的,而JSON的Number类型不区分整数和浮点数——Struct里所有数字都会被统一存储为double类型(对应Protobuf Value的number_value字段),所以不管你传入的是整数还是浮点数,最终都会以浮点数形式呈现。
解决方案
1. 自定义Protobuf消息类型(推荐)
如果需要严格区分整数和浮点数,不要用默认的Struct,而是自己定义匹配业务结构的Protobuf消息,明确指定字段类型。
比如针对你的输入层配置,编写.proto文件:
syntax = "proto3"; message LayerConfig { string class_name = 1; message ConfigDetail { // 用optional字段处理原字典中的None,proto3支持可选字段 optional int32 batch_input_dim_1 = 1; int32 batch_input_dim_2 = 2; // 明确指定为整数类型 string dtype = 3; bool sparse = 4; bool ragged = 5; string name = 6; } ConfigDetail config = 2; }
将.proto编译为Python代码后,用这个自定义消息类型解析数据,就能精准保留整数类型。原字典中的None可通过optional字段表示,后续使用时再转换回None即可。
2. 转换后手动修正类型(临时 workaround)
如果必须使用Struct,只能在转换完成后手动遍历结构,把需要的浮点数转回整数:
import json from google.protobuf import struct_pb2 layer_config = { 'class_name': 'InputLayer', 'config': { 'batch_input_shape': (None, 32), 'dtype': 'float32', 'sparse': False, 'ragged': False, 'name': 'input_5' } } # 转换为Struct s = struct_pb2.Struct() s.update(layer_config) # 定义工具函数,读取值时自动修正整数类型 def get_typed_value(val): if val.HasField('number_value'): num = val.number_value return int(num) if num.is_integer() else num elif val.HasField('null_value'): return None return val.string_value if val.HasField('string_value') else val.bool_value # 读取并修正batch_input_shape的值 corrected_shape = [get_typed_value(v) for v in s['config']['batch_input_shape'].list_value.values] print(corrected_shape) # 输出 [None, 32]
这种方式只能在读取数据时做类型修正,Struct内部存储的还是浮点数,适合无法修改消息类型的场景。
内容的提问来源于stack exchange,提问作者techytushar
相关产品推荐
相关产品推荐

