How to serialize/deserialize to Protobuf a JSON object in JavaScript

939 Views Asked by At

I have a .proto schema obtained from a json structure:

package mypackage;
syntax="proto3";

import "item.proto";
import "google/protobuf/any.proto";

message Header {
    uint32 status_code = 1;
    double execute_time = 2;
    string ip = 3;
}
message Body {
    repeated Item item_list = 1;
}
message Message {
    Header header = 1;
    Body body = 2;
}
message Response {
    Message message = 1;
}

where item.proto is

package mypackage;
syntax = "proto3";

import "google/protobuf/any.proto";

message Thumbnail {
    string source = 1;
    uint32 width = 2;
    uint32 height = 3;
}
message Item {
    uint32 pageid = 1;
    string title = 2;
    string modified = 3;
    Thumbnail thumbnail = 10;
    string pageName = 12;
}

And I want to load it and serialize to and from JSON using Google's protobuf library and proto3-json-serializer

run().catch(err => console.log(err));

  async function run() {
    const root = await protobuf.load('schema/dummy.proto');
    const Message = root.lookupType('mypackage.Response');
    console.log(Message);
    const jsonResponse = {
      "message": {
        "header": {
          "status_code": 200,
          "execute_time": 1.18,
          "ip": "127.0.0.1"
        },
        "body": {
          "item_list": [{
            "pageid": 10345,
            "title": "test item",
            "modified": "2023-01-01:15:22:44",
            "thumbnail": {
              "source": "https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png",
              "width": 172,
              "height": 178
            }
          }
          ]
        }
      }
    };

It comes out the message packet is valid

// verifies that a plain JavaScript object satisfies the requirements of a valid message and thus can be encoded without issues
var err = Message.verify(jsonResponse);
console.log(`valid: ${!err}`);
// true

but when encoding it

// encodes a message instance or valid plain JavaScript object. This method does not implicitly verify the message
const buf = Message.encode(jsonResponse).finish();
const obj = Message.decode(buf);
console.log(obj);

I get message Response with only the ip field filled in, while other flat fields ans well as nested array objects item_list are empty:

Response {
  message: Message {
    header: Header { ip: '127.0.0.1' },
    body: Body { itemList: [] }
  }
}

The same happens using fromProto3JSON and then toProto3JSON:

// To deserialize an object from proto3 JSON, we must know its type (as returned by root.lookupType('...'))
const deserialized = serializer.fromProto3JSON(Message, jsonResponse);
console.log(deserialized);
const serialized = serializer.toProto3JSON(deserialized);
console.log(serialized);

resulting in

{ message: { header: { ip: '127.0.0.1' }, body: {} } }

and the same using fromObject and then toProto3JSON

//converts any non-valid plain JavaScript object to a message instance
var message = Message.fromObject(jsonResponse);
console.log(message);
const serialized2 = serializer.toProto3JSON(message);
console.log(serialized2);

Is there any errors in .proto definition or in the provide json object?

0

There are 0 best solutions below