JSON.stringify or how to serialize binary data as base64 encoded JSON?

25.3k views Asked by At

I have a Javascript object which will consists of a non-cyclic object hierarchy with parameters and child objects. Some of these objects may hold binary data loaded from files or received via XHRs (not defined yet if Blob, ArrayBuffer or something else).

Normally I would use JSON.stringify() to serialize it as JSON but how can I then specify that binary data will be base64 encoded?

What binary data object (Blob, ArrayBuffer,...) would you recommend me then?

EDIT: Other data formats than plain JSON is not an option.

2

There are 2 answers

0
Joonas On

For blobs it makes more sense to convert the Blobs in the object to base64 beforehand and then stringify the object. This is because there is no reliable way to synchronously convert a blob to base64, and thus the replacer function is not a viable choice here.

const blobToBase64 = (blob) => {
  return new Promise((resolve) => {
    const reader = new FileReader();
    reader.readAsDataURL(blob);
    reader.onloadend = function () {
      resolve(reader.result);
    };
  });
};

(async () => {
  const b64 = await blobToBase64(blob);
  const jsonString = JSON.stringify({blob: b64});
  console.log(jsonString);
})();

Getting a blob from parsed JSON is then as simple as

const parsed = JSON.parse(jsonString);
const blob = await fetch(parsed.blob).then(res => res.blob());
console.log(blob);
2
Sebastian Barth On

JSON.stringify indeed did the trick with two possible solutions:

a) The replacer function called to decide how to serialize a value.

function replacer(key, value) {
  if (typeof value === "string") {
    return undefined;
  }
  return value;
}

var foo = {foundation: "Mozilla", model: "box", week: 45, transport: "car", month: 7};

var jsonString = JSON.stringify(foo, replacer);

b) Define a toJSON() member function for the object.

var obj = {
  foo: 'foo',
  toJSON: function () {
    return '{ "foo": "' +  + '" }';
  }
};
JSON.stringify(obj);      // '{ "foo": "Zm9v" }'

Plz up this comment instead if that works for you, too.