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

  1. Initial Observations Received a base64-encoded string that:

Looked like binary when decoded

Contained embedded, readable JSON text

  1. 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

  1. Compression & Framing Hypotheses Attempted gzip/inflate decompression — all failed

Tried .decodeDelimited() in case of length-prefixed framing — no success

  1. 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)

  1. 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