Security News
ESLint is Now Language-Agnostic: Linting JSON, Markdown, and Beyond
ESLint has added JSON and Markdown linting support with new officially-supported plugins, expanding its versatility beyond JavaScript.
Typeson is a JavaScript library that allows you to serialize and deserialize complex data types to and from JSON. It extends the capabilities of JSON.stringify and JSON.parse to handle more complex data structures such as Dates, Maps, Sets, and more.
Serialization and Deserialization
Typeson allows you to serialize and deserialize complex data types like Date objects. The example shows how to serialize an object containing a Date and then deserialize it back to its original form.
const Typeson = require('typeson');
const typeson = new Typeson();
const obj = { date: new Date() };
const serialized = typeson.stringify(obj);
const deserialized = typeson.parse(serialized);
console.log(serialized); // Output: {"date":"2023-10-05T14:48:00.000Z"}
console.log(deserialized); // Output: { date: 2023-10-05T14:48:00.000Z }
Custom Type Handlers
Typeson allows you to define custom type handlers for serialization and deserialization. The example demonstrates how to handle RegExp objects by defining custom test, replace, and revive functions.
const Typeson = require('typeson');
const typeson = new Typeson();
// Define a custom type handler for RegExp
const regExpType = {
test: x => x instanceof RegExp,
replace: x => x.toString(),
revive: x => new RegExp(x.slice(1, x.lastIndexOf('/')), x.slice(x.lastIndexOf('/') + 1))
};
// Register the custom type handler
typeson.register({ RegExp: regExpType });
const obj = { pattern: /abc/i };
const serialized = typeson.stringify(obj);
const deserialized = typeson.parse(serialized);
console.log(serialized); // Output: {"pattern":"/abc/i"}
console.log(deserialized); // Output: { pattern: /abc/i }
Handling Circular References
Typeson can handle circular references in objects. The example shows how to serialize and deserialize an object with a circular reference using Typeson's circular preset.
const Typeson = require('typeson');
const typeson = new Typeson.Typeson().register(Typeson.presets.circular);
const obj = {};
obj.self = obj;
const serialized = typeson.stringify(obj);
const deserialized = typeson.parse(serialized);
console.log(serialized); // Output: {"self":"~"}
console.log(deserialized); // Output: { self: [Circular] }
Flatted is a lightweight library for serializing and deserializing JavaScript objects with circular references. Unlike Typeson, Flatted focuses specifically on handling circular references and does not support custom type handlers or complex data types like Dates or Maps.
CircularJSON is another library for serializing and deserializing objects with circular references. It is similar to Flatted but has a different API. CircularJSON also does not support custom type handlers or complex data types, making it less versatile than Typeson.
SuperJSON is a library that extends JSON to support more complex data types like Dates, Maps, and Sets. It is similar to Typeson in its ability to handle complex data structures, but it does not offer the same level of customization for defining custom type handlers.
Preserves types over JSON, BSON or socket.io
Only 3.4kb minified. ~1k when gzipped. {
{foo: 1} // {"foo":1}
{foo: "bar"} // {"foo":"bar"}
{foo: new Date()} // {"foo":1464049031538, "$types":{"foo":"Date"}}
{foo: new Set([new Date()])} // {"foo":[1464127925971], "$types":{"foo":"Set","foo.0":"Date"}}
{foo: {sub: /bar/i}} // {"foo":{"sub":{"source":"bar","flags":"i"}}, "$types":{"foo.sub":"RegExp"}}
{foo: new Int8Array(3)} // {"foo":"AAAA", "$types":{"foo":"Int8Array"}}
new Date() // {"$":1464128478593, "$types":{"$":{"":"Date"}}}
NOTE: Typeson by itself wont support these types. Register the types you need:
var typeson = new Typeson().register([
require('typeson-registry/types/date'),
require('typeson-registry/types/set'),
require('typeson-registry/types/regexp'),
require('typeson-registry/types/typed-arrays')
]);
or if you want support for all built-in javascript classes:
var typeson = new Typeson().register([
require('typeson-registry/presets/builtin')
]);
JSON can only contain simple types: strings, numbers, booleans, arrays and objects. This module makes it possible to serialize any type over JSON or other media, such as Date, Error, ArrayBuffer, etc. Typeson is just JSON that complements non-trivial properties with types. It adds a metadata property "$types" to the result that maps each non-trivial property to a type name. The type name is a reference to a registered type specification that you need to have the same on both the stringifying and the parsing side.
typeson-registry contains encapsulation rules for standard javascript types such as Date, Error, ArrayBuffer, etc. Pick the types you need, use a preset or write your own.
(*) Typeson is a CommonJS module so you must use a web bundler like browserify, webpack or systemjs to use it in the browser or in a web worker.
var typeson = new Typeson().register({
Date: [
x => x instanceof Date, // test function
d => d.getTime(), // encapsulator function
number => new Date(number) // reviver function
],
Error: [
x => x instanceof Error, // tester
e => ({name: e.name, message: e.message}), // encapsulator
data => {
// reviver
var e = new Error (data.message);
e.name = data.name;
return e;
}
]
});
// Encapsulate to a JSON friendly format:
var jsonFriendly = typeson.encapsulate({date: new Date(), e: new Error("Oops")});
// Stringify using good old JSON.stringify()
var json = JSON.stringify(jsonFriendly);
// {"date":1464049031538,e:{"name":"Error","message":"Oops"},"$types":{"date":"Date","e":"Error"}}
// Parse using good old JSON.parse()
var parsed = JSON.parse(json);
// Revive back again:
var revived = typeson.revive(parsed);
Socket.io can stream ArrayBuffers as real binary data. This is more efficient than encapsulating it in base64/JSON. Typeson can leave certain types, like ArrayBuffer, untouched, and leave the stringification / binarization part to other libs.
What socket.io doesn't do though, is preserving Dates, Errors or your custom types.
So to get the best of two worlds:
Typeson.encapsulate()
to generate an object ready for socket-io emit()Typeson.revive()
to revive the encapsulated object at the other end.var Typeson = require('typeson'),
presetSocketIo = require('typeson-registry/presets/socketio.js');
var TSON = new Typeson()
.register(presetSocketIo)
.register({
CustomClass: [
x => x instanceof CustomClass,
c => {foo: c.foo, bar: c.bar},
o => new CustomClass(o.foo, o.bar)
]
});
var array = new Float64Array(65536);
array.fill(42, 0, 65536);
var data = {
date: new Date(),
error: new SyntaxError("Ooops!"),
array: array,
custom: new CustomClass("foo", "bar")
};
socket.emit('myEvent', TSON.encapsulate(data));
The encapsulate() method will not stringify but just traverse the object and return a simpler structure where certain properties are replaced with a substitue. Resulting object will also have a $types property containing the type metadata.
Packing it up at the other end:
socket.on('myEvent', function (data) {
var revived = TSON.revive(data);
// Here we have a true Date, SyntaxError, Float64Array and Custom to play with.
});
NOTE: Both peers must have the same types registered.
The BSON format can serialize object over a binary channel. It supports just the standard JSON types plus Date, Error and optionally Function. You can use Typeson to encapsulate and revive other types as well with BSON as bearer. Use it the same way as shown above with socket.io.
Web Workers have the onmessage
and postMessage()
communication channel that has built-in support for transferring structures using the structured clone algorithm. It supports Date and ArrayBuffer but not Errors or your own custom classes. To support Error and custom types over web worker channel, register just the types that are needed (Errors and your custom types), and then use Typeson.encapsulate() before posting message, and Typeson.revive() in the onmessage callback.
Creates an instance of Typeson, on which you may configure additional types to support, or call encapsulate(), revive(), stringify() or parse() on.
{
cyclic?: boolean, // Default true
}
Whether or not to support cyclic references. Default true unless explicitely set to false. If this property is false, the parsing algorithm becomes a little faster and in case a single object occurs on multiple properties, it will be duplicated in the output (as JSON.stringify() would do). If this property is true, several instances of same object will only occur once in the generated JSON and other references will just contain a pointer to the single reference.
var Typeson = require('typeson');
var presetUniversal = require('typeson-registry/presets/universal');
var typeson = new Typeson()
.register (presetUniversal);
var tson = typeson.stringify(complexObject);
console.log(tson);
var obj = typeson.parse(tson);
A map between type identifyer and type-rules. Same structure as passed to register(). Use this property if you want to create a new Typeson containing all types from another Typeson.
var commonTypeson = new Typeson().register([
require('typeson-registry/presets/builtin')
]);
var myTypeson = new Typeson().register([
commonTypeson.types, // Derive from commonTypeson
myOwnSpecificTypes // Add your extra types
]);
Generates JSON based on given obj. If given obj has special types or cyclic references, the produce JSON will contain a $types property on the root where type info relies.
var TSON = new Typeson().register(require('typeson-registry/types/date'));
TSON.stringify ({date: new Date()});
Output:
{"date": 1463667643065, "$types": {"date": "Date"}}
Parses Typeson genereted JSON back into the original complex structure again.
var TSON = new Typeson().register(require('typeson-registry/types/date'));
TSON.parse ('{"date": 1463667643065, "$types": {"date": "Date"}}');
Encapsulates an object but leaves the stringification part to you. Pass your encapsulated object further to socket.io, postMessage(), BSON or indexedDB.
var encapsulated = typeson.encapsulate(new Date());
var revived = typeson.revive(encapsulated);
assert (revived instanceof Date);
Revives an encapsulated object. See encapsulate().
{TypeName: [tester, encapsulator, reviver]}
or an array of such.
Function that tests whether an instance is of your type and returns a truthy value if it is.
Function that maps you instance to a JSON-serializable object.
Function that maps you JSON-serializable object into a real instance of your type.
var typeson = new Typeson();
typeson.register({
Date: [
x => x instanceof Date, // tester
date => date.getTime(), // encapsulator
obj => new Date(obj) // reviver
],
RegExp: [
x = x instanceof RegExp,
re => [re.source, re.flags],
a => new RegExp (a[0], a[1])
]
});
console.log(typeson.stringify({d: new Date(), r:/foo/gi }));
// {"d":1464049031538,"r":["foo","gi"],$types:{"d":"Date","r":"RegExp"}}
typeson-registry contains ready-to-use types to register with your Typeson instance.
FAQs
Preserves types over JSON, BSON or socket.io
The npm package typeson receives a total of 209,139 weekly downloads. As such, typeson popularity was classified as popular.
We found that typeson demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
ESLint has added JSON and Markdown linting support with new officially-supported plugins, expanding its versatility beyond JavaScript.
Security News
Members Hub is conducting large-scale campaigns to artificially boost Discord server metrics, undermining community trust and platform integrity.
Security News
NIST has failed to meet its self-imposed deadline of clearing the NVD's backlog by the end of the fiscal year. Meanwhile, CVE's awaiting analysis have increased by 33% since June.