TypedJSON icon indicating copy to clipboard operation
TypedJSON copied to clipboard

Serializing odd-length ArrayBuffer fails

Open sumbricht opened this issue 2 years ago • 1 comments

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

  1. Serializing to bas64 instead of a sequence of UTF16 characters
  2. Padding the ArrayBuffer with a zero (creating a new Uint8Array and copying the old one over) and then serializing to { data: string, padded: boolean }
  3. 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 }
  4. 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 :-)

sumbricht avatar Jun 28 '23 10:06 sumbricht

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.

sumbricht avatar Feb 28 '25 16:02 sumbricht