Skip to main content

Serde

The eridu-tech/serde component provides seamless way to serialize/deserialize data and adding custom serialization/deserialization logic for custom data types.

Initial configuration​

./samples/serde-initial-config.ts
import { Serde } from "eridu-tech/serde";
import { SuperJsonSerdeAdapter } from "eridu-tech/serde/super-json-serde-adapter";

export const serde = new Serde(new SuperJsonSerdeAdapter());

Serde basics​

Serializing and deserializing values​

Here is an example of serializing and deserializing a value.

./samples/serialize.ts
import { serde } from "./serde-initial-config.js";

const serializedValue = serde.serialize({
name: "abra",
age: 20,
});

const deserializedValue = serde.deserialize(serializedValue);

Custom serialization and deserialization logic​

The registerCustom method offers control over serialization and deserialization behavior.

./samples/register-custom.ts
import type { ISerdeTransformer } from "eridu-tech/serde/contracts";
import { serde } from "./serde-initial-config.js";

type ISerializedUser = {
version: "1";
name: string;
age: number;
};

class User {
static readonly serdeTransformer: ISerdeTransformer<User, ISerializedUser> =
{
name: "User",
isApplicable(value: unknown): value is User {
return value instanceof User;
},
deserialize(serializedValue: ISerializedUser): User {
return new User(serializedValue.name, serializedValue.age);
},
serialize(deserializedValue: User): ISerializedUser {
return {
version: "1",
name: deserializedValue.name,
age: deserializedValue.age,
};
},
};

constructor(
readonly name: string,
readonly age: number,
) {}
}

serde.registerCustom(User.serdeTransformer);
info

Note the ISerdeTranformer object can be dynamically created.

Patterns​

Usage with other components​

When using Serde class instance there is no need to call serialize and deserialize manually. Because components like Cache handle it automatically through their adapter.

./samples/with-cache.ts
import { Serde } from "eridu-tech/serde";
import { SuperJsonSerdeAdapter } from "eridu-tech/serde/super-json-serde-adapter";
import { RedisCacheAdapter } from "eridu-tech/cache/redis-cache-adapter";
import { Cache } from "eridu-tech/cache";
import { ListCollection } from "eridu-tech/collection";
import type { ICollection } from "eridu-tech/collection/contracts";
import { Redis } from "ioredis";

const serde = new Serde(new SuperJsonSerdeAdapter());
serde.registerCustom(ListCollection.serdeTransformer);

const cache = new Cache<ICollection<string>>({
adapter: new RedisCacheAdapter({
database: new Redis("YOUR_REDIS_CONNECTION_STRING"),
serde,
}),
});

const listCollection = new ListCollection(["a", "b", "c", "d", "e"]);

await cache.add("list", listCollection);

const deserializedListCollection = await cache.get("list");
if (deserializedListCollection) {
// Logs "c"
console.log(deserializedListCollection.getOrFail(2));
}
info

Note you should use one Serde class instance accross all components and register all serializable objects before component usage.

Separating serialization, deserialization and registering custom serialization/deserialization logic​

The library includes 4 additional contracts:

  • ISerializer - Allows only for serialization.

  • IDeserializer - Allows only for deserialization.

  • ISerde - Allows for both serialization and deserialization.

  • ISerderRegister - Allows only for registering custom serialization/deserialization logic.

  • IFlexibleSerde – Allows for both serialization, deserialization and for registering custom serialization/deserialization and deserialization logic.

This separation makes it easy to visually distinguish the 4 contracts, making it immediately obvious that they serve different purposes.

Further information​

For further information refer to eridu-tech/serde API docs.