bufbuild / protobuf-es

Protocol Buffers for ECMAScript. The only JavaScript Protobuf library that is fully-compliant with Protobuf conformance tests.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Utility method to remove methods from a message

thesiti92 opened this issue · comments

Right now if you want to store a protobuf in redux, it complains that there are unserializable members on it (its methods). Theres a PlainMessage utility type already, but it would be really useful to have a function which transforms a Message type to a PlainMessage and strips off the methods. The .toJson method doesnt work because it produces output that has different types from the generated Message type (structs, oneofs, etc...).

Thanks!

i think this could also be solved by making a utility type for the result of Message.toJson thats strongly typed

Hey @thesiti92, there is a very simple option to convert a Message to a PlainMessage. You can use the spread syntax to create a shallow clone:

const plain = { ...myMessage };

It is a shallow clone, so any message fields (including repeated fields and maps) will still be instances of Message with the corresponding methods.

To do the same with any nested message fields, you can make use of structuredClone():

import {Message, PlainMessage} from "@bufbuild/protobuf";

/**
 * Convert any Message to a PlainMessage - a clone as a plain object without
 * methods.
 */
export function toPlainMessage<T extends Message<T>>(message: T): PlainMessage<T> {
  return structuredClone(message) as PlainMessage<T>;
}

Usage:

const plain = toPlainMessage(myMessage);

Note that structuredClone() is a relatively new feature, and may not supported in older runtimes.

I think the issue here is with struct messages, that would mean they just have the raw .fields member and that's it. The most ergonomic solution would be converting them to their json representation but then the plain message type would be wrong. I think I can write some utils to reach the desired outcome though.

Do you mean google.protobuf.Struct? Yes, since it represents an arbitrary JSON object, it's often more convenient to process it in its JSON form in JS.

You can always go from PlainMessage<T> to Message<T> with new T(). That includes google.protobuf.Struct:

const json = new Struct(plain).toJson();

gotcha sounds good, a few utils will do the trick it seems. thanks!