首页 > 解决方案 > 使 gRPC 消息 JSON 可序列化

问题描述

我有一个包含重复标量值的 gRPC 定义。

例如


message Request {
  bool dryrun = 1;   
  bool verbose = 2;
  bool enabled = 3;
  float ratio = 4;
  int32 count = 5;
  string somevar = 6;
  bool withcondition = 7;
  bool nocondition = 8;
  float portion = 9;
  int32 population = 10;
  string xvars = 11;
  string singleoption = 12;
  repeated int32 multioptions = 13;
}

我注意到当这个请求被发送到 Python 服务器时,mylist它被转换为 a RepeatedScalarContainer,它不是 JSON 可序列化的。一些 SO 问题建议我使用

from google.protobuf.json_format import MessageToJson
serialized = MessageToJson(original)

将 protobuf 消息转换为有效的 JSON 对象。但就我而言,对收到的 Python 对象执行上述操作会给我一个截断的对象

{
  "enabled": true,
  "ratio": 0.5,
  "count": 100,
  "somevar": "/input",
  "withcondition": true,
  "singleoption": "option1",
  "multioptions": [
    1,
    3
  ]
}

您可以看到缺少一堆消息属性。

作为一种解决方法,我仍然可以提取接收到的对象的属性以恢复数据并将它们转换为可通过蛮力序列化的 JSON,但这看起来很丑陋且不稳定。这是我的方式

    def handle_request(request):
        all_attrs = dir(request)
        i_last_private_attr = next((a for a, attr in enumerate(reversed(all_attrs)) if attr.startswith('_')), None)
        if not i_last_private_attr:
            _logger.error('Failed to find any request')
            return
        i_first_arg_attr = len(all_attrs) - i_last_private_attr
        req_dict = {attr: getattr(request, attr) for attr in all_attrs[i_first_arg_attr:]}
        for k, v in req_dict.items():
            if isinstance(v, Iterable) and not isinstance(v, (dict, list, tuple, str)):
                req_dict[k] = list(req_dict[k])

我应该如何使接收到的原始 gRPC 请求像只包含内置原始值类型的 Python 对象一样工作?

标签: pythonjsongrpcgrpc-pythongrpc-node

解决方案


自己解决了。

有一个选项including_default_value_fieldsjson_format.MessageToJson()当设置为 时False,所有默认字段都不会打印为 JSON,尽管它们是通过网络物理发送的。

不幸的是,默认情况下该选项已关闭。

设置为 后True,问题就消失了。


推荐阅读