Serializing odd-length ArrayBuffer fails
Serializing objects containing ArrayBuffer properties works only if the ArrayBuffer is of even length.
In case of odd length, the following error is thrown:
RangeError: byte length of Uint16Array should be a multiple of 2
The cause is quite evident when looking at the serializer code, as it uses Uint16Arrays under the hood:
function convertAsArrayBuffer(buffer: ArrayBuffer) {
// ArrayBuffer -> 16-bit character codes -> character array -> joined string.
return Array.from(new Uint16Array(buffer))
.map(charCode => String.fromCharCode(charCode)).join('');
}
I'm not sure what would be the best change to make this work for odd lengths as well; so far my ideas would be
- Serializing to bas64 instead of a sequence of UTF16 characters
- Padding the ArrayBuffer with a zero (creating a new Uint8Array and copying the old one over) and then serializing to
{ data: string, padded: boolean } - Splitting off the last byte of an odd-length ArrayBuffer and treating it separately:
- Treat the main portion using the current approach
- Treat the last byte as number (0-255) or undefined (for even-length ArrayBuffer)
- Serialize the whole ArrayBuffer to
{ data: string, lastByte: number | undefined }
- Any other creative ideas?
I'm happy to contribute if you'd like; in that case please let me know your preference on the approach. If you feel it's quicker for you to "just do it", that's also fine :-)
For anyone blocked by TypedJSON issues: my own software heavily relied on TypedJSON and had to apply numerous hacks for issues in TypedJSON that are not getting fixed. I loved TypedJSON but unfortunately had to move on as there has not been a single fix in 4 years now.
Therefore I created the similarly powerful library json-class-serializer heavily inspired by TypedJSON, which addresses all my issues (and hopefully yours). It's pretty much a drop-in replacement if you don't rely on reflect-metadata, which I'm not supporting (as this was the cause of most of my issues). If you rely on reflect-metadata, just specify the constructors of properties other than string/number/boolean and then it most likely just works.
Please feel free to give it a try if you feel the urge to move away from TypedJSON but don't want to do any heavy re-engineering. And please don't hate on me for the advertisement here as I have contributed to TypedJSON as well and opened many still-open issues :-).
You can find my library at @sumbricht/json-class-serializer and gladly open issues there if you feel something's missing / not working correctly.