Decoding a Protobuf-Encoded Base64 JSON Wrapper Without a Schema
Why Would I Need to Do This?
Look, all I'm saying is that someday you might be working on an app with a lot of heavy data coming through to the front end. And another developer might just send you some serialized/compressed data. And when you ask for the schema for deserialization, they might say "I just ran Serializer.serialize. Running Serializer.deserialize deserializes the data instantly, I don't know what to tell you."
🛠️ Final Solution Summary The C# code used:
csharp Copy Edit Serializer.Serialize(stream, jsonString); This means:
The data is a Protobuf message with one string field
That field contains the full JSON string
The .proto schema is extremely simple
✅ Final Working .proto proto Copy Edit
message WrappedJson {
string json = 1;
}
🧰 Final Working Node.js Decoder js Copy Edit
import protobuf from 'protobufjs';
import fs from 'fs';
// Read base64 string from file (strip trailing whitespace & line breaks)
const base64 = fs.readFileSync('data.txt', 'utf8').trim().replace(/[\r\n]+/g, '');
const buffer = Buffer.from(base64, 'base64');
protobuf.load('wrapped_json.proto', (err, root) => {
if (err) throw err;
const WrappedJson = root.lookupType('WrappedJson');
const decoded = WrappedJson.decode(buffer);
const jsonStr = decoded.json;
const parsed = JSON.parse(jsonStr);
console.log('✅ Parsed object:', parsed);
});
Full Investigation Timeline
- Initial Observations Received a base64-encoded string that:
Looked like binary when decoded
Contained embedded, readable JSON text
- Tried Mapping with a Full .proto Schema Wrote full schema with nested messages (e.g. Contour, Coordinate, etc.)
Encountered repeated errors:
invalid wire type
decoded values
buffer overflows / incorrect field offsets
- Compression & Framing Hypotheses Attempted gzip/inflate decompression — all failed
Tried .decodeDelimited() in case of length-prefixed framing — no success
- Talked to the Engineer Confirmed: protobuf-net was used
The payload was just a JSON string, not a structured message
Serialization was done directly via Serializer.Serialize(stream, jsonString)
- Fixed Schema & Successfully Decoded Created a .proto file with one field
Used protobufjs to decode the base64 buffer
Parsed the embedded JSON string to retrieve the actual data
🔍 Notes & Best Practices If you're unsure about the structure, scan the decoded buffer for:
\x0a (field 1, string)
Embedded { or [ characters
Always trim() and .replace(/\r?\n/g, '') base64 read from files
Use .decode() (not decodeDelimited) if there's no length prefix
When devs say “protobuf” but no .proto exists, they may be serializing raw strings