grpc в javaScript - как избавиться от fieldsMap
Всем доброго времени. Никто не работал с grpc в ангуларе?
google_protobuf_struct_pb.Struct.toObject() даёт странный массив
{
"fieldsMap": [
[
"value",
{
"nullValue": 0,
"numberValue": 0,
"stringValue": "Значение!",
"boolValue": false
}
]
]
}
Слов нет, как удобно получается
const data = this.field.data?.fieldsMap;
this.field.data?.fieldsMap[0][1]
if(data && data[0] && data[0][1] && data[0][1][FieldValueType.STRING]?.length > 0) {
this.fieldValueType = FieldValueType.STRING;
}
Никто не знает, что это, и как с этим жить, учитывая, что Struct находятся в глубине jspb.Message и непосредственно вызвать у него .toJavaScript() не представляется возможным, приходится юзать весь jspb.Message.toObject()??
Лично я решил для себя проблему, переопределив один из методов мессег (Some - объект jspb.Message в сгенерированном через protoc коде, а getValue в нем дает Struct, который стандартно тоже приводится через toObject)
const SomeToObject = Some.toObject;
Some.toObject = function (includeInstance: boolean, msg: Some) : Some.AsObject
{
const rowResult = SomeToObject(includeInstance, msg);
rowResult.value = msg.getValue()?.toJavaScript();
return rowResult;
};
Почему-то у jspb.Message метод toObject не в prototype и я получаю его в константу SomeToObject, затем я получаю стандартный результат через эту функцию, затем подменяю value, которое уже получено через toObject с fieldsMap, на новое, полученное через toJavaScript.
Вот здесь https://github.com/grpc/grpc-web/issues/315 тоже получают объек стандартным способо, а затем пробегается по результату, чтобы получить имена функций, получает их,приводит к строке - короче много телодвижений только, чтобы получить json. Такие дела.
Можно также переопределить сразу функцию google_protobuf_struct_pb.Struct.toObject, но у нас уже стоит некоторое количество костылей для fieldsMap и возможно, оно там где-то внутри grpc используется. Может кто-то знает менее костыльный способ?
jspb.Message.toObject вызывает toObject у всех своих потомков, в том числе и у тех, который Struct и не существует метода, чтобы сделать для jspb.Message - toObject, а для Struct - toJavaScript.
Вот допустим пришло мне сообщение со множеством разных параметров.
export class AnyResponse extends jspb.Message {
getView(): View | undefined;
setView(value?: View): OperationResponse;
hasView(): boolean;
clearView(): OperationResponse;
getAnyParam(): string;
setAnyParam(value: string): OperationResponse;
........
И допустим, где-то в глубине этой кучи данных есть значение value, которое тоже надо получить.
response.getSome()?.getItems()?.getValue()?.toObject() даст нам значение вот в таком виде
"value": {
"fieldsMap": [
[
"id",
{
"nullValue": 0,
"numberValue": 1,
"stringValue": "",
"boolValue": false
}
],
[
"anyNname",
{
"nullValue": 0,
"numberValue": 0,
"stringValue": "Здесь строка",
"boolValue": false
}
],
Это не то, что мне нужно, мне было бы гораздо удобнее получить нормальный объект.
Если я применю response.getSome()?.getItems()?.getValue()?.toJavaScript(), то получится то, что нужно.
"value": {
"id": 1,
"name": "Здесь строка",
.......
}
Но мне необходимо конвертнуть в нормальный объект со значениями весь AnyResponse, который не имеет метода toJavaScript, а он сам и его дети вниз по цепочке являются наследниками jspb.Message и соответственно, имеют только toObject. А value уже google_protobuf_struct_pb.Struct и он может быть обработан через toJavaScript. Вообще-то там массив, и .getValue() нужно еще и циклом перебрать, например. Я пытаюсь упростить код и опустить ненужную информацию, чтобы проблема наглядно сохранилаь.