1.0.2 • Published 7 years ago

packberry v1.0.2

Weekly downloads
3
License
MIT
Repository
github
Last release
7 years ago

PackBerry

JSON.stringify() and JSON.parse() works just fine for serializing straightforward data, but what about class instances?

PackBerry lets you declare what's special about your classes, so that you can serialize and deserialize them:

// Make an instance
let theIncredibles = new Movie('The Incredibles', 2004);
console.log(theIncredibles.getCentury()); // `21`

// Serialize it…
let serializedIncredibles = serializer.toJSON(theIncredibles);

// Deserialize it…
let unpackedIncredibles = serializer.fromJSON(serializedIncredibles);

// It still works!
console.log(unpackedIncredibles instanceof Movie); // `true`
console.log(unpackedIncredibles.getCentury()); // `21`

Usage

After installing PackBerry with npm install packberry, import it in your code and get your very own serializer:

import { Serializer } from pacbkberry;
let serializer = new Serializer('my-app-namespace');

(The namespace will be used in the serialized data, to distinguish your app's classes from your possible dependencies' classes.)

Then register your classes with your serializer:

class Movie {
	constructor(name, year) {
		this.name = name;
		this.year = year;
	}
	
	getCentury() {
		return Math.floor((this.year - 1) / 100) + 1;
	}
}

serializer.register(Movie, {
	fields: ['name', 'year']
});

And tada! Your class is (un)packable:

let serializedAmelie = serializer.toJSON(new Movie('Amélie', 2001));

register()

The register() method accepts various options, to mix and match depending on the complexity of your classes.

fields

With just a fields parameter, PackBerry will pack the listed fields, and then use them in order to call your constructor when unpacking:

serializer.register(Movie, {
	fields: ['name', 'year']
});

// means that when unpacking, PackBerry will call `new Movie(name, year)`

unpack

If your constructor can't simply be called with the packed parameters, you can tell PackBerry how to make instances using unpack:

serializer.register(Movie, {
	fields: ['name', 'year'],
	unpack: packed => new Movie(packed.name, packed.year)
});

pack

If you can't list all the fields in advance, use pack instead of fields, and do the packing yourself. The returned value must be readily JSON-serializable.

serializer.register(Movie, {
	pack: value => {
		return {
			name: value.name,
			year: value.year
		};
	},
	unpack: packed => new Movie(packed.name, packed.year)
});

When you do this, you'll want to use Serializer.toPacked(value) to pack any instance your class contains.
You can't use pack without specifying unpack as well.

Caveats

They could be resolved without dramatically overhauling PackBerry, but as of today these limitations apply:

  • To identify a class, PackBerry relies on its name. This might break if you minify your code.
  • PackBerry doesn't understand inheritance right now. You'll have to register each subclass separately.
  • PackBerry includes class identifiers in the packed data, to know which class to instantiate when unpacking; this is quite verbose.
  • Some native JavaScript classes (such as Int8Array) don't currently have built-in PackBerry support. RegExp state is not conserved when packing.

Development

Clone PackBerry and run npm install.

You can then build the release version using npm run build, and run the sandbox, a handy testbed, using npm run sandbox.