4

I'm using the 'bson' npm package in the browser for converting / serializing a JSON object to BSON. The documentation says that it returns a Node.js buffer. The documentation of Node.js says that a buffer is of type 'Uint8Array'. Now I want to send this Uint8Array in another JSON object (infoJSON) but JSON does not support Uint8Array. I tried to convert the buffer (Uint8Array) to a simple array, inserting it in the JSON object (infoJSON) and then I convert it back to Uint8Array directly out of the JSON object. But this new Uint8Array can not be deserialized back to the original person object (see the result). It is broken.

Why I'm using BSON? I want to split the original object into multiple chunks to send it through a WebRTC data channel which has a limitation of data size. I need to be able to identify each chunk (type). It is the reason why I am using nested objects.

  var personJSON = { 'name': 'sarah' } // JSON
  var personBuffer = Bson.serialize(personJSON) // Uint8Array
  var personArray = Array.from(personBuffer) // Simple array
  var infoJSON = { 'count': 1, 'person': personArray } // Inserting array into JSON
  var personUint8Array = Uint8Array.from(infoJSON.person) // Converting array back to Uint8Array
  console.log('deserializedObj:')
  console.log(Bson.deserialize(personUint8Array))

Result:

result

La0x1
  • 145
  • 1
  • 2
  • 11

3 Answers3

3

You can't send binary data or not JSON objects through a JSON. If you want to do it, then I suggest you to encode your unit8array in base64, something like this:

  let base64 = btoa(String.fromCharCode.apply(null, personUint8Array));

Now you can simply attach that string into another JSON and send it in. To cast it back to unit8Array just do:

  let personUint8Array = new Unit8Array(atob(base64).split("").map(
      (char)=>char.charCodeAt(0)
    )
   );

I suggest you to avoid trying to use another object types than those supported by JSON, if you need to do that, then you probably don't need JSON format.

agelbess
  • 4,249
  • 3
  • 20
  • 21
Gustavo Topete
  • 1,246
  • 1
  • 9
  • 15
3

This is because Bson.serialize and Bson.deserialize use a Node.js like Buffer object.

You can correct this by using the underlying ArrayBuffer to create a Uint8Array (test online) and use then use Buffer.from :

var personJSON = { 'name': 'sarah' } // JSON
var personBuffer = new Uint8Array(Bson.serialize(personJSON).buffer) // Uint8Array
var personArray = Array.from(personBuffer) // Simple array
var infoJSON = { 'count': 1, 'person': personArray } // Inserting array into JSON
var personUint8Array = Uint8Array.from(infoJSON.person) // Converting array back to Uint8Array
console.log('deserializedObj:')
console.log(Bson.deserialize(Buffer.from(personBuffer)))
Fathy
  • 4,939
  • 1
  • 23
  • 25
  • Tried your suggestion but I get the same result as above. – La0x1 Mar 13 '18 at 19:45
  • Woops, sorry. `Bson.deserialize` needs a Node.js like `Buffer`. If you're using Webpack it's builtin else use [`buffer`](https://www.npmjs.com/package/buffer). Answer updated. – Fathy Mar 13 '18 at 20:13
1

I really love the above answers... Finally I ended up to

const payload = {hello: 'alex'}
const array = Array.from(serialize(payload))
const json = JSON.stringify(array)
const payload2 = deserialize(Uint8Array.from((JSON.parse(json)))
console.log(payload === payload2)

The first one converts the payload to an array that can be added into any object that will be converted to JSON.

The second one converts the json back to the original payload

agelbess
  • 4,249
  • 3
  • 20
  • 21