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
相关产品推荐
相关产品推荐

