protobufjs / protobuf.js

Protocol Buffers for JavaScript & TypeScript.
Other
9.86k stars 1.41k forks source link

Overwriting basic functions in custom classes #879

Open yagop opened 7 years ago

yagop commented 7 years ago

protobuf.js version: 6.8.0

Hello, I'm trying to overwriting toObject in a custom class, but it seems is not being possible or I'm doing it wrong.

const protobuf = require("protobufjs");

const proto = `
package main;

message Decimal {
  required sint64 mantisa = 1;
  required sint32 exponent = 2;
}

message Message {
  required Decimal a = 1;
  required Decimal b = 2;
}`;

const root = protobuf.parse(proto).root;

const Message = root.lookupType('main.Message');
const Decimal = root.lookupType('main.Decimal');

const DecimalCtor = function (...args) {
  console.log('DecimalCtor constructor called with:', ...args);
};

DecimalCtor.toObject = function (...args) {
  console.log('DecimalCtor.toObject called with:', ...args);
};

DecimalCtor.prototype.toObject = function (...args) {
  console.log('DecimalCtor.prototype.toObject called with:', ...args);
}; 

Decimal.ctor = DecimalCtor;

const msg = Message.create({
  a: Decimal.create({
    mantisa: 1,
    exponent: 0
  }),
  b: Decimal.create({
    mantisa: 1,
    exponent: 0
  })
});

const buffer = Message.encode(msg).finish();
const decoded = Message.decode(buffer);

Message.toObject(decoded);

Output:

➜  /tmp node proto.js
DecimalCtor constructor called with: { mantisa: 1, exponent: 0 }
DecimalCtor constructor called with: { mantisa: 1, exponent: 0 }
DecimalCtor constructor called with:
DecimalCtor constructor called with:
yagop commented 6 years ago

:thinking:

ape-casear commented 2 years ago

You can overwrite function toObject by using Protobuf.wrappers

const protobuf = require('protobufjs')

protobuf.wrappers['.main.Decimal'] = {
    toObject(message, options) {
        const originOutput = this.toObject(message, options)
        if (message.type === 2) {
            originOutput.content = UserProfile.toObject(UserProfile.decode(Buffer.from(message.content, 'base64')))
        }
        return originOutput
    },
    fromObject(object) {
        console.log('user fromObject')
        return this.toObject(object)
    },
}

const proto = `
package main;

message Decimal {
  required sint64 mantisa = 1;
  required sint32 exponent = 2;
  optional uint32 type = 3;
  optional bytes content = 4;
}

message User {
    required Decimal user = 1;
}

message UserProfile {
    required string name = 1;
}
`

const root = protobuf.parse(proto).root

const UserProfile = root.lookupType('main.UserProfile')
const Decimal = root.lookupType('main.Decimal')
const User = root.lookupType('main.User')

const options = {
    keepCase: true,
    bytes: String, // bytes as base64 encoded strings
}

const user = User.create({
    user: Decimal.create({
        mantisa: 1,
        exponent: 0,
        type: 2,
        content: UserProfile.encode({ name: 'Tom' }).finish(),
    }),
})

const buffer2 = User.encode(user).finish()
const decoded2 = User.decode(buffer2)

console.log(User.toObject(decoded2, options))