# Implementation

Serializers are processors which handle serialization/deserialization of custom classes (not natively supported Java types outside of the YAML spec).

All serializers follow this common pattern:

* **Deserialization:** Map -> Object of custom type
* **Serialization:** Object of custom type -> Map

BoostedYAML uses [`StandardSerializer.getDefault()`](https://javadoc.io/static/dev.dejvokep/boosted-yaml/1.0/dev/dejvokep/boostedyaml/serialization/standard/StandardSerializer.html#getDefault--) by default, but you can change it [via the settings](https://dejvokep.gitbook.io/boostedyaml/settings/generalsettings#serializer).

## StandardSerializer

### Type key

Type key defines key, at which information about your class will be stored in the Map (when serialized, see "Serialization" at the top).

StandardSerializer.getDefault() uses `==`, which means in serialized form, your object at route `"x"` could look like this:

```yaml
x:
  ==: me.user.project.Person
  name: Martin
  age: 20
```

To use custom keys, create your own instance of StandardSerializer, e.g.

```java
new StandardSerializer("_");
```

### Registering your class

To make your type recognizable by **that instance of** StandardSerializer, you must register it:

```java
<T> StandardSerializer#register(@NotNull Class<T> clazz, @NotNull TypeAdapter<T> adapter)
```

The serializer now knows that **exact** (no subtypes) type thanks to the adapter provided. TypeAdapter is called to serialize/deserialize the type. Now you can freely set/get your custom type from sections.

You can also register an alias for your custom type using this method. Aliases are commonly used to maintain compatibility even after the class' canonical name has been changed (e.g. the class was moved to other package).

{% hint style="danger" %}
**Serializers are instantiable.**

Types are registered to that instance of StandardSerializer; won't be available for another instance of the serializer.
{% endhint %}

### Example

Let's suppose we have the following class:

```java
public class Person {
    
    private String name;
    private int age;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public String getName() {
        return name;
    }
    
    public int getAge() {
        return age;
    }

}
```

Assuming we would like to use both the name and age field, our adapter could look like this:

```java
TypeAdapter<Person> adapter = new TypeAdapter<Person>() {
    
    @NotNull
    Map<Object, Object> serialize(@NotNull Person object) {
        Map<Object, Object> map = new HashMap<>();
        map.put("name", object.getName());
        map.put("age", object.getAge());
        return map;
    }
    
    @Nullable
    T deserialize(@NotNull Map<Object, Object> map) {
        String name = map.get("name");
        int age = (int) map.get("age");
        return new Person(name, age);
    }
    
}
```

{% hint style="info" %}
If needed, convert `Map<Object, Object>` to `Map<String, Object>` using [`toStringKeyedMap(@NotNull Map<?, ?> map)`](https://javadoc.io/static/dev.dejvokep/boosted-yaml/1.0/dev/dejvokep/boostedyaml/serialization/standard/TypeAdapter.html#toStringKeyedMap-java.util.Map-) method.
{% endhint %}

If we left the serializer on default (that means, [`StandardSerializer.getDefault()`](https://javadoc.io/static/dev.dejvokep/boosted-yaml/1.0/dev/dejvokep/boostedyaml/serialization/standard/StandardSerializer.html#getDefault--)), we would need to register the type to **that** serializer:

```java
StandardSerializer.getDefault().register(Person.class, adapter);
```

We're done! :tada:

## Custom serializers

If you'd like to create and use a custom serializer, you would need to implement YamlSerializer class. Please look at the [class documenation](https://javadoc.io/doc/dev.dejvokep/boosted-yaml/latest/dev/dejvokep/boostedyaml/serialization/YamlSerializer.html) for more information.
