> For the complete documentation index, see [llms.txt](https://kirudev-oss.gitbook.io/serde.ts/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kirudev-oss.gitbook.io/serde.ts/quickstart.md).

# Quickstart

If your project has simple needs for serialization & deserialization, e.g. cross-session persistence, *serde* can get you started quickly.

If your data type has no specific needs and consists only of [Standard Types](/serde.ts/standard-types.md), *serde* works out of the box:

```typescript
import Serde from '@kiruse/serde';
import { expect } from 'chai';

const serde = Serde().standard();

const ref = {
    foo: 'foo',
    bar: 42,
    baz: 69,
};
const bytes = serde.serialize(ref);
expect(serde.deserialize(bytes)).to.deep.equal(ref);
```

*serde* supports references, including cyclic references, and will reconstruct an object with identical hierarchy than your input:

```typescript
import Serde from '@kiruse/serde';

const serde = Serde().standard();

// self-referential object
const ref: any = {};
ref.ref = ref;

const value = serde.deserialize(serde.serialize(ref));
value === value.ref;
```

## setSimple Method

The `Serde` protocol is highly customizeable to various degrees. Indicative of its name, the `Serde.prototype.setSimple` method allows some more control than serializing plain old objects:

```typescript
import Serde, { SERDE, StandardProtocolMap } from '@kiruse/serde';
import { expect } from 'chai';

type MyProtocolMap = StandardProtocolMap & {
    'my-foo': Foo;
}

class Foo {
    [SERDE] = 'my-foo' as const;
    constructor(public readonly id: number) {}
}

const serde = Serde<MyProtocolMap>().standard()
    .setSimple('my-foo',
        (foo: Foo) => foo.id,
        (id: Foo['id']) => new Foo(id),
    );
```

However, there is a **caveat**: due to the way \*serde\* internally handles references you only have direct access to first-level properties, i.e. you cannot access nested objects. \*serde\* promises that these special references are resolved and the object properly reconstructed after the call to `deserialize`. Within the deserialization process, certain rules must be considered. Read further at [References](/serde.ts/details/references.md)

## set Method

Save for writing your own protocol, the highest degree of control is offered by the `Serde.prototype.set` method which grants you access to the `Writer` and `Reader` used during de/serialization as well as their contexts:

```typescript
import Serde, { SERDE, StandardProtocolMap } from '@kiruse/serde';

type MyProtocolMap = StandardProtocolMap & {
    'my-foo': Foo;
}

class Foo {
    [SERDE] = 'my-foo' as const;
    constructor(public readonly id: number) {}
}

const serde = Serde().standard()
    .set('my-foo',
        (ctx, writer, foo: Foo) => {
            writer.writeUint32(foo.id);
        },
        (ctx, reader) => {
            return new Foo(reader.readUint32());
        },
    );
```

Find more information on `Readers` and `Writers` in their respective chapter [Readers & Writers](/serde.ts/details/readers-and-writers.md)

The `ctx` arguments

## SerdeAlter

An alternate variant of `Serde`, `SerdeAlter` overrides `set` and `setSimple` to augment its given protocol map. Due to the smenatics of TypeScript, you will typically find yourself daisy-chaining `set` and `setSimple` calls and assigning the final result to your `serde` variable (or whatever else you call it).

Because `SerdeAlter` does not know what your final protocol map will look like as you build it, your de/serializers do not get knowledge of the protocol map, simply because it's impossible. If this is needed, prefer using `Serde` instead, at the cost of some more verbose code.

```typescript
import { SERDE, SerdeAlter } from '@kiruse/serde';

class Foo {
    [SERDE] = 'my-foo' as const;
    constructor(public data: any) {}
}

const serde = SerdeAlter().standard()
    .setSimple('my-foo',
        (ctx, writer, foo: Foo) => {
            ctx.serde.serialize(foo.data, ctx);
        },
        (ctx, reader): Foo => {
            const data = ctx.serde.deserialize(reader, ctx);
            return new Foo(data);
        },
    );
```

Note that the overridden `set` and `setSimple` methods also require you to define the type of a value in the de/serializers - it then uses this type to populate the protocol map.
