You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

gRPC序列化含任意属性对象失败问题求助

gRPC Mock服务器返回Map类型响应序列化失败问题

问题背景

我正在开发一个可配置的Mock gRPC服务器,运行在Docker容器中,作为后端服务的模拟实例。通过Proto文件和配置初始化每个实例,指定监听的方法及响应数据。使用@grpc/grpc-js和@grpc/proto-loader,目前已实现返回任意标量值、数组及已知结构对象的功能,但在生成Map类型的任意对象时出现问题:gRPC服务器无法识别传入的对象并报错。

客户端报错信息

Error: 13 INTERNAL: Error serializing response: .Result.testObject: object expected
    at callErrorFromStatus (***/test/grpc/node_modules/@grpc/grpc-js/build/src/call.js:31:19)
    at Object.onReceiveStatus (***/test/grpc/node_modules/@grpc/grpc-js/build/src/client.js:192:76)
    at Object.onReceiveStatus (***/test/grpc/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:360:141)
    at Object.onReceiveStatus (***/test/grpc/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:323:181)
    at ***/test/grpc/node_modules/@grpc/grpc-js/build/src/resolving-call.js:99:78
    at process.processTicksAndRejections (node:internal/process/task_queues:77:11)
for call at
    at ServiceClientImpl.makeUnaryRequest (***/test/grpc/node_modules/@grpc/grpc-js/build/src/client.js:160:32)
    at ServiceClientImpl.<anonymous> (***/test/grpc/node_modules/@grpc/grpc-js/build/src/make-client.js:105:19)
    at file://***/test/grpc/index.mjs:14:10
    at file://***/test/grpc/index.mjs:18:3
    at ModuleJob.run (node:internal/modules/esm/module_job:217:25)
    at async ModuleLoader.import (node:internal/modules/esm/loader:316:24)
    at async loadESM (node:internal/process/esm_loader:34:7)
    at async handleMainPromise (node:internal/process/run_main:66:12) {
  code: 13,
  details: 'Error serializing response: .Result.testObject: object expected',
  metadata: Metadata {
    internalRepr: Map(2) { 'content-type' => [Array], 'date' => [Array] },
    options: {}
  }
}

共用Proto文件

syntax = "proto3";

service TestApi {
  rpc Execute(None) returns (Result);
}

message None {}

message Result {
  map<string, Value> testObject = 1;
}

message Value {
  oneof kind {
    bool boolValue = 1;
    int32 intValue = 2;
    double doubleValue = 3;
    string stringValue = 4;
  }
}

服务器处理函数

export function handler(call, callback) {
  try {
    const response = generateValues('$', outputs); // Generate random response
    console.log(response);
    callback(null, response);
  } catch (e) {
    console.error(e);
    callback(e, null);
  }
}

当前生成的响应示例

{
  testObject: {
    VmZWD: false,
    VXiRwi: 28.087891844342792,
    cjCTDFD: false,
    inYZS: 6,
    AYKahk: ' xsyflf szsnwb ush',
    pgUT: 23.19160119367565
  }
}

已尝试的操作

  • 将Value改为google.protobuf.Any(已添加相关导入)
  • 调整proto-loader加载函数的json、object、oneOf参数为true或false

注意事项

无法将map改为其他结构,因为生产环境的Proto文件已使用该类型。


解决方案

核心问题是你生成的响应不符合Proto定义的结构。testObject是map<string, Value>类型,而Value是包含oneof字段的消息体,不能直接传入标量值,必须包装成符合Value结构的对象。

修正后的响应结构

{
  testObject: {
    VmZWD: { boolValue: false },
    VXiRwi: { doubleValue: 28.087891844342792 },
    cjCTDFD: { boolValue: false },
    inYZS: { intValue: 6 },
    AYKahk: { stringValue: ' xsyflf szsnwb ush' },
    pgUT: { doubleValue: 23.19160119367565 }
  }
}

修改generateValues函数

根据值的类型,将其包装到对应字段的对象中:

  • 布尔值 → { boolValue: 值 }
  • 整数 → { intValue: 值 }
  • 浮点数 → { doubleValue: 值 }
  • 字符串 → { stringValue: 值 }

优化proto-loader配置

确保启用oneof支持,建议配置如下:

const packageDefinition = protoLoader.loadSync(
  'your-proto-file.proto',
  {
    keepCase: true,
    longs: String,
    enums: String,
    defaults: true,
    oneofs: true,
    objects: true
  }
);

这样修改后,gRPC就能正确序列化Map类型的响应了。


内容的提问来源于stack exchange,提问作者Abion47

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 12:33:32