这是 RESTful API 响应 json:
{
"success": true,
"data": {
"loginname": "mrdulin",
"avatar_url": "https://avatars1.githubusercontent.com/u/1147375?v=4&s=120",
"githubUsername": "mrdulin",
"create_at": "2012-09-09T05:26:58.319Z",
"score": 15835,
"recent_topics": [
{
"id": "5c6d11d033b0b629ac8434ef",
"author": {
"loginname": "mrdulin",
"avatar_url": "https://avatars1.githubusercontent.com/u/1147375?v=4&s=120"
},
"title": "grpc and Node.js",
"last_reply_at": "2019-05-11T04:22:18.616Z"
}
],
"recent_replies": []
}
}
UserServiceImpl.ts
:
export class UserServiceImpl implements IUserServiceServer {
public async getUserByLoginname(call: ServerUnaryCall<GetUserByLoginnameRequest>, callback: sendUnaryData<GetUserByLoginnameResponse>) {
const loginname = call.request.getLoginname();
const url = `${config.CNODE_API_URL}/user/${loginname}`;
try {
const res = await axios.get(url);
const data = res.data.data;
// map API response js plain object to GetUserByLoginnameResponse
const grcpResponse = new GetUserByLoginnameResponse();
grcpResponse.setSuccess(res.data.success);
const user = new UserDetail();
user.setAvatarUrl(data.avatar_url);
user.setLoginname(data.loginname);
user.setGithubusername(data.githubUsername);
user.setCreateAt(data.create_at);
user.setScore(data.score);
const recentReplies = data.recent_replies.map((po) => {
const reply = new RecentReply();
reply.setId(po.id);
reply.setTitle(po.title);
const lastReplyAt = new google_protobuf_timestamp_pb.Timestamp();
lastReplyAt.fromDate(new Date(po.last_reply_at));
reply.setLastReplyAt(lastReplyAt);
const author = new UserBase();
author.setLoginname(po.author.loginname);
author.setAvatarUrl(po.author.avatar_url);
reply.setAuthor(author);
return reply;
});
const recentTopics = data.recent_topics.map((po) => {
const topic = new TopicBase();
topic.setId(po.id);
topic.setTitle(po.title);
topic.setLastReplyAt(po.last_reply_at);
const author = new UserBase();
author.setLoginname(po.author.loginname);
author.setAvatarUrl(po.author.avatar_url);
topic.setAuthor(author);
return topic;
});
user.setRecentRepliesList(recentReplies);
user.setRecentTopicsList(recentTopics);
grcpResponse.setData(user);
callback(null, grcpResponse);
} catch (error) {
console.error(error);
const metadata = new Metadata();
metadata.set('url', url);
const ErrGetUserByLoginname: ServiceError = {
code: status.INTERNAL,
name: 'getUserByLoginnameError',
message: 'call CNode API failed',
metadata,
};
callback(ErrGetUserByLoginname, null);
}
}
}
如您所见,我必须GetUserByLoginnameResponse
手动将普通的 javascript 对象(API 响应)映射到类。这是繁琐且低效的。
我正在使用静态代码生成,因此GetUserByLoginnameResponse
该类是根据.proto
文件中定义的 IDL 生成的。
user.service.proto
:
service UserService {
rpc GetUserByLoginname(GetUserByLoginnameRequest)
returns (GetUserByLoginnameResponse);
}
message GetUserByLoginnameRequest { string loginname = 1; }
message GetUserByLoginnameResponse {
UserDetail data = 1;
bool success = 2;
}
message UserDetail {
string loginname = 1;
string avatar_url = 2;
string githubUsername = 3;
string create_at = 4;
int32 score = 5;
repeated share.TopicBase recent_topics = 6;
repeated reply.RecentReply recent_replies = 7;
}