Serialising objects in JavaScript with tanagra.js
--
There are many occasions on which you might want to serialise object data, then retrieve it later as an instance of the same class. Consider the following use-case: your website authenticates users when they log on, looks up the user record from the database, then embellishes it with data from a number of external services via API calls. In order to avoid having to do these (expensive) look-ups every time a user logs in, the site caches this user data; so that the cache won’t be invalidated on service restart (or perhaps to share the cache between different instances in a high-availability cluster), it is stored in Redis, necessitating that the user objects be serialised into a format that Redis can handle. When retrieving users from the Redis cache, they should be returned as instances of the user class.
This is relatively straightforward to achieve in statically-typed languages such as c#. However, the dynamic nature of JavaScript makes the problem a little trickier. Whilst ES6 introduced classes, the fields on these classes (and their types) aren’t defined until they are initialised (which may not be when the class is instantiated), and the return-types of fields and functions aren’t defined at all in the schema. What’s more, the structure of the class can easily be changed at runtime - fields can be added or removed, types can be changed, etc. (Whilst this is possible using reflection in c#, reflection represents the ‘dark arts’ of that language, and thus developers expect it to break functionality.)
tanagra.js (Trekkies will get the reference) is a new serialisation library which aims to solve some of these problems, allowing objects to be serialised, and later deserialised into instances of their original classes. It works by exposing a function to be used when defining classes, which allows the developer to specify all the types referenced by the class. (The function can be seen as equivalent to the Serializable attribute in c#.) Consider the following example:
const serializable = require('tanagra-core').serializable
class Foo {
constructor(bar, baz1, baz2, fooBar1, fooBar2) {
this.someNumber = 123
this.someString = 'hello, world!'
this.bar = bar // a complex object with a prototype
this.bazArray = [baz1, baz2]
this.fooBarMap = new Map([
['a', fooBar1]…