JSON-dry

JSON-dry allows you to stringify objects containing circular references,
dates, regexes, ...
It can also be used to serialize and revive instances of your own classes.
Installation
$ npm install json-dry
Usage
Basic example
This is a basic example of stringifying an object (containing multiple references to the same object) and parsing it again.
var Dry = require('json-dry');
var obj = {};
var ref = {
date : new Date(),
regex : /test/i
};
obj.reference_one = ref;
obj.reference_two = ref;
obj.date = ref.date;
var dried = Dry.stringify(obj);
var undried = Dry.parse(dried);
undried.reference_one == undried.reference_two;
undried.reference_one.date == undried.date;
Reviving instances
Let's create an example class you might want to serialize and revive:
function Person(options) {
this.firstname = options.firstname;
this.lastname = options.lastname;
}
Person.prototype.fullname = function fullname() {
return this.firstname + ' ' + this.lastname;
};
var jelle = new Person({firstname: 'Jelle', lastname: 'De Loecker'});
jelle.fullname();
So now we've created a very basic class, let's register the class and add the 2 required methods for serializing & reviving.
Dry.registerClass(Person);
Person.prototype.toDry = function toDry() {
return {
value: {
firstname : this.firstname,
lastname : this.lastname
}
};
};
Person.unDry = function unDry(value) {
var result = new Person(value);
return result;
};
Now let's try stringifying it:
var dried = Dry.stringify(jelle);
var undried = Dry.parse(dried);
undried.fullname();
toObject
While Dry.stringify
will return you with a json-valid string, Dry.toObject
will give you a valid simplified object.
In fact: Dry.stringify
is just a function that performs JON.stringify
on Dry.toObject
's output.
Why would you want to use this? Things like Workers
and IndexedDB
communicate data using the structured clone algorithm. So instead of performing expensive stringify operations you can just use these objects.
Cloning objects & instances
JSON-Dry offers a specialized clone
method. While in theory you could clone an object by drying end reviving it, like so:
var cloned = Dry.parse(Dry.toObject(jelle))
This is 14x slower than using clone
, because toObject
needs to generate paths, escape certain string values and create wrapper objects. These expensive things can be ignored when cloning:
var cloned = Dry.clone(jelle);
Clone methods
If you've added a toDry
and unDry
method to your class, by default the clone
method will use those to create the clone.
However, you can also create another method that gets precedence:
dryClone
Person.prototype.dryClone = function dryClone(seen_map, custom_method) {
return new Person({
firstname : this.firstname,
lastname : this.lastname
});
}
Custom clone methods
The clone
method takes an extra parameter called custom_method
. If you're cloning something that has a function property with the same name, that'll be used.
This can be used when you want to redact certain parts, for example:
Person.prototype.specialOccasionClone = function specialOccasionClone(seen_map, custom_method) {
return new Person({
firstname : this.firstname[0] + '.',
lastname : this.lastname
});
};
var special_clone = Dry.clone(jelle, 'specialOccasionClone');
special_clone.fullname();