I'm using Buffer
on my node server and Buffer
on my Javacript client.
For the purposes of saving bytes, I'm looking to send my data to the server through websockets as binary as opposed to JSON.
So, if I had the Javascript object of [ 5, false, 55, "asdf" ]
, I'd like to convert that to the buffer on the client right before sending it. Maybe something like this:
object.toBuffer('int16', 'bool', 'int16', 'utf8');
and read it on the server something like this:
var obj = buffer.read('int16', 'bool', 'int16', 'utf8');
I'm looking at current solutions and it looks like I may have to just do a lot of concat
ing, specifying byte offsets/lengths, converting from ints to booleans, etc.
Is there a better way?
Edit: Here's how I think you currently have to do it. I guess my issue is just that it's too verbose and error-prone and I'm looking for a more concise and elegant way to do it, because this operation will be performed in many different places in my code.
// On client for [ 5, false, 55, "test" ]
const writeFirst = Buffer.allocUnsafe(2);
writeFirst.writeInt16LE(5, 0);
const writeSecond = Buffer.allocUnsafe(1);
writeSecond.writeUInt8(0);
const writeThird = Buffer.allocUnsafe(2);
writeThird.writeInt16LE(55, 0);
const writeFourth = Buffer.from('test');
const result = Buffer.concat([writeFirst, writeSecond, writeThird, writeFourth]);
// On server for reading buffer of [ 5, false, 55, "test" ]
const readFirst = result.readInt16LE(0);
const readSecond = Boolean(result.readUInt8(2));
const readThird = result.readInt16LE(3);
const readFourth = result.toString('utf8', 5);
Edit #2: Was googling around and I think I might want something like protocol buffers. I'm not exactly sure what they are yet or if they apply but it looks like you can specify a schema in a file for all your messages and then serialize your JSON objects to that schema and have it return a buffer, which you can then deserialize using the same schema on the client/other server. I'm going to look in to this some more.
The Buffer. toJSON() method returns the buffer in JSON format. Note: The JSON. Stringify() is the method which can also be used to return the data in JSON format.
var buf = new Buffer("Simply Easy Learning", "utf-8"); Though "utf8" is the default encoding, you can use any of the following encodings "ascii", "utf8", "utf16le", "ucs2", "base64" or "hex".
JsonBuffer is the entry point for using the library: it handles the memory management and calls the parser.
The toJSON() method returns a JSON object based on the Buffer object.
A buffer's first argument must be a: String, Buffer, ArrayBuffer, Array, or array-like object.
Taking that information into account, we could implement what you are looking for by creating a buffer from a String. It would look something like the following:
let json = [ 5, false, 55, 'asdf' ];
let buffer = Buffer.from(JSON.stringify(json));
console.log('Buffer: ', buffer); // Buffer: <Buffer 5b 20 35 2c 20 66 61 6c 73 65 2c 20 35 35 2c 20 22 61 73 64 66 22 20 5d>
Then you can bring your JSON back like so:
let converted = JSON.parse(buffer);
console.log('Parsed to json', converted); // Parsed to json [ 5, false, 55, 'asdf' ]
When we are in NodeJS environment we have much better options than, Buffer.from(JSON.stringify(data))
.
Performance wise JSON.stringify + Buffer.from() is ok, but will not work out if the object contains ArrayBuffer, and if done, then very inefficient.
Its easy to use and built into the Node.js binary.
Its fastest and most space efficient among all the serializers of its kind.
const { serialize, deserialize } = require("v8")
const photo = {
name: "rabbit",
height: 1220,
width: 1440,
tinyThumbnail: jpegFileAsBuffer,
mediumThumbnail: anotherJpegFileAsBuffer,
description: "some string data",
metaData: {
tags: ["rabbit", "animal", "runner"],
type: "image/jpeg"
}
}
const photoSerializedAsBuffer = serialize(photo)
const deserialisedBack = deserialize(photo)
But only issue is, this only works for NodeJS. And C++ if you wish to use "v8" library(I personally not a fan of doing that).
Performance wise its close to v8 parser, but it can be adapted in all platforms where MongoDB is supported, NodeJS, JS in web, Java, C++, rust, ruby, python....
The usage is exactly like v8 serialization API
const { serialize, deserialize } = require("bson")
const photo = {
name: "rabbit",
height: 1220,
width: 1440,
tinyThumbnail: jpegFileAsBuffer,
mediumThumbnail: anotherJpegFileAsBuffer,
description: "some string data",
metaData: {
tags: ["rabbit", "animal", "runner"],
type: "image/jpeg"
}
}
const photoSerializedAsBuffer = serialize(photo)
const deserialisedBack = deserialize(photo)
But it can get difficult when BSON types kick in. But this should not be an issue if the object structure is know, and its unlikely that one may not know the object structure while dealing with cross platform stuff.
However a quick, solution for that in NodeJS is to use bson-buffer
This not a full proof solution, but works great for NodeJS and planning to soon launch this for web JS.
tabular-json-node
And due to its simple tabular structure we can support this is other platforms too. Feel free to connect if anyone want to collaborate on this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With