GRPC Node.js+MySQL服务端如何序列化Unit供Android客户端接收?
问题分析与解决方案
问题的核心在于服务端返回的数据结构与.proto定义不匹配,导致客户端无法正确解析Unit数据。结合你的代码细节,具体修正步骤如下:
1. 先确认.proto文件的核心定义
首先必须明确UnitFindResponse和Unit的字段类型,这是数据匹配的基础:
场景1:按ID查询应返回单个Unit对象
如果你的查询逻辑是根据ID获取单条数据,.proto应该定义为单个Unit字段:
syntax = "proto3"; message Unit { int32 id = 1; string name = 2; } message UnitFindResponse { string result = 1; Unit unit = 2; // 单个Unit对象 }
此时服务端的问题是返回了数组类型的unit(res.rows是数组),而不是单个对象。修改Node.js服务端代码:
find: ({request: {id}}, callback) => { cn.executeQuery(`SELECT id, name FROM tb WHERE id=${id}`, (res) => { // 从查询结果数组中取出第一个元素(按ID查询应返回单条) const targetUnit = res.rows.length > 0 ? res.rows[0] : {}; callback(null, { result: res.result, unit: targetUnit // 返回单个对象而非数组 }); }); }
场景2:需要返回多个Unit对象
如果业务逻辑允许返回多条数据,.proto需定义为重复字段:
message UnitFindResponse { string result = 1; repeated Unit unit = 2; // 数组类型的Unit }
此时客户端代码需要修改为获取列表:
UnitServiceGrpc.UnitServiceBlockingStub stub = UnitServiceGrpc.newBlockingStub(mChannel); UnitFindRequest request = UnitFindRequest.newBuilder().setId(id).build(); UnitFindResponse reply = stub.find(request); // 改为获取列表而非单个对象 List<Unit> responseList = reply.getUnitList(); if (!responseList.isEmpty()) { Unit response = responseList.get(0); // 按需取第一个元素 }
2. 额外检查事项
- 字段名一致性:确保服务端返回的对象字段名(
id、name)与.proto中Unit的字段名完全匹配,大小写、拼写不能出错。 - SQL注入风险:你的服务端代码直接拼接SQL参数
id=${id}存在注入风险,建议使用参数化查询:cn.executeQuery(`SELECT id, name FROM tb WHERE id=?`, [id], (res) => { // 后续逻辑不变 });
内容的提问来源于stack exchange,提问作者Luciano Coelho
相关产品推荐
相关产品推荐

