Skip to main content

Custom Types

Similar to the global JSON seria allow to pass a replacer and reviver function but the behaviour in our case is different.

When using a stringify function the replacer function is called for each value, the replacer take the value to stringify and return a string which represents the serialized value or undefined to ignore the value.

For the parse operation the reviver function is called again for each value and should convert the value converted before to its actual representation, similar to the reviver we return undefined to ignore the value.

Example

Serializing URL

For URL we check if the value is an URL and then return a value in the format:

$<tag><data>

This is the format seria use to represents any non-serializable value like Date and the tag is used to look up the value.

const input = {
url: new URL("http://127.0.0.1:3000/seria?hello=world"),
};

const json = stringify(input, (val) => {
if (val instanceof URL) {
return `$1${val.href}`; // $1 is our custom tag for URL
}

return undefined;
});

For parsing because the serialized value is a string we check both, if is a string and if contains the tag we used, then we just need to stripped the tag and create the URL from the data.

const value: any = parse(json, (val) => {
if (typeof val === "string" && val.startsWith("$1")) {
return new URL(val.slice(2)); // remove the tag $1
}

return undefined;
});

Serializing RegExp

For RegExp we check if the value is an RegExp and then return a value in the format:

$<tag><data>

This is the format seria use to represents any non-serializable value like RegExp and the tag is used to look up the value.

const input = {
url: new URL("http://127.0.0.1:3000/seria?hello=world"),
};

const json = stringify(input, (val) => {
if (val instanceof RegExp) {
return `$2${val.toString()}`; // `$2` is our custom tag for RegExp
}

return undefined;
});

And for parsing because the string value.

const value: any = parse(json, (val) => {
if (typeof val === "string" && val.startsWith("$2")) {
const parts = val.slice(2); // remove the tag $2
const body = parts.slice(1, parts.lastIndexOf("/"));
const flags = parts.slice(parts.lastIndexOf("/") + 1);
return new RegExp(body, flags);
}

return undefined;
});