python中 protobuf序列化json时 使用MessageToJson中文乱码,浮点精度问题
在使用google.protobuf 的json_format.MessageToJson时,出现了中文字段变成了ascii编码了,如下:"WeaponNickName": "\u6c99\u9e70",因此查阅pythongoogle.protobuf中json_format.MessageToJson的引用关系如下:在json_format.py中有如下代码:...
·
在使用google.protobuf 的json_format.MessageToJson时,出现了中文字段变成了ascii编码了,如下:
"WeaponNickName": "\u6c99\u9e70",
因此查阅python google.protobuf中json_format.MessageToJson的引用关系如下:
在json_format.py中有如下代码:
def MessageToJson(
message,
including_default_value_fields=False,
preserving_proto_field_name=False,
indent=2,
sort_keys=False,
use_integers_for_enums=False,
descriptor_pool=None,
float_precision=None):
"""Converts protobuf message to JSON format.
Args:
message: The protocol buffers message instance to serialize.
including_default_value_fields: If True, singular primitive fields,
repeated fields, and map fields will always be serialized. If
False, only serialize non-empty fields. Singular message fields
and oneof fields are not affected by this option.
preserving_proto_field_name: If True, use the original proto field
names as defined in the .proto file. If False, convert the field
names to lowerCamelCase.
indent: The JSON object will be pretty-printed with this indent level.
An indent level of 0 or negative will only insert newlines.
sort_keys: If True, then the output will be sorted by field names.
use_integers_for_enums: If true, print integers instead of enum names.
descriptor_pool: A Descriptor Pool for resolving types. If None use the
default.
float_precision: If set, use this to specify float field valid digits.
Returns:
A string containing the JSON formatted protocol buffer message.
"""
printer = _Printer(
including_default_value_fields,
preserving_proto_field_name,
use_integers_for_enums,
descriptor_pool,
float_precision=float_precision)
return printer.ToJsonString(message, indent, sort_keys)
float_precision:这个字段就是设置浮点精度的,我可以设置为3,保留3位小数。
接着往下看printer.ToJsonString:
def ToJsonString(self, message, indent, sort_keys):
js = self._MessageToJsonObject(message)
return json.dumps(js, indent=indent, sort_keys=sort_keys)
发现最终调用的是大家熟悉的json.dumps函数,进入看(截取源码片段),
def dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True,
allow_nan=True, cls=None, indent=None, separators=None,
default=None, sort_keys=False, **kw):
"""Serialize ``obj`` to a JSON formatted ``str``.
If ``skipkeys`` is true then ``dict`` keys that are not basic types
(``str``, ``int``, ``float``, ``bool``, ``None``) will be skipped
instead of raising a ``TypeError``.
If ``ensure_ascii`` is false, then the return value can contain non-ASCII
characters if they appear in strings contained in ``obj``. Otherwise, all
such characters are escaped in JSON strings.
原来这里有个ensure_ascii选项,默认是True,但是上面ToJsonString函数没有传参,因此会变成asciil编码了,因此我们可以修改源码,把ensure_ascii 设置为false。
改变就是逆向的过程,具体操作如下:
在ToJsonString中,增加ensure_ascii参数
def ToJsonString(self, message, indent, sort_keys, ensure_ascii):
js = self._MessageToJsonObject(message)
return json.dumps(js, indent=indent, sort_keys=sort_keys, ensure_ascii=ensure_ascii)
在MessageToJson中加入参数:
def MessageToJson(
message,
including_default_value_fields=False,
preserving_proto_field_name=False,
indent=2,
sort_keys=False,
use_integers_for_enums=False,
descriptor_pool=None,
float_precision=None,
ensure_ascii = True):
"""Converts protobuf message to JSON format.
Args:
message: The protocol buffers message instance to serialize.
including_default_value_fields: If True, singular primitive fields,
repeated fields, and map fields will always be serialized. If
False, only serialize non-empty fields. Singular message fields
and oneof fields are not affected by this option.
preserving_proto_field_name: If True, use the original proto field
names as defined in the .proto file. If False, convert the field
names to lowerCamelCase.
indent: The JSON object will be pretty-printed with this indent level.
An indent level of 0 or negative will only insert newlines.
sort_keys: If True, then the output will be sorted by field names.
use_integers_for_enums: If true, print integers instead of enum names.
descriptor_pool: A Descriptor Pool for resolving types. If None use the
default.
float_precision: If set, use this to specify float field valid digits.
Returns:
A string containing the JSON formatted protocol buffer message.
"""
printer = _Printer(
including_default_value_fields,
preserving_proto_field_name,
use_integers_for_enums,
descriptor_pool,
float_precision=float_precision)
return printer.ToJsonString(message, indent, sort_keys, ensure_ascii)
在调用的地方
_json_result = json_format.MessageToJson(_data, True, True, 2, True, False, None, 3)
更多推荐
已为社区贡献2条内容
所有评论(0)