# `Chronicle.Serialization`
[🔗](https://github.com/Cratis/Chronicle.Elixir/blob/main/lib/chronicle/serialization.ex#L4)

Encodes event and read model structs to Chronicle's JSON wire format and decodes them back.

This is the single place where the client decides how a struct travels over the wire, so
the JSON schema generated by `Chronicle.Schemas.JsonSchemaGenerator` and the payload that is
sent can never drift apart.

## Key styles

  * `:camel` — struct field names are rendered as `camelCase` at **every depth** (events).
  * `:identity` — struct field names are kept as-is (read models).

Keys of plain maps are **data**, not field names, and are never transformed.

## Value rules

  * A `Chronicle.Concept` is written as its wrapped value.
  * Nested structs (and structs inside lists and maps) are written field by field.
  * `DateTime`, `NaiveDateTime`, `Date` and `Time` are written as ISO 8601 strings.
  * `MapSet` is written as a list; non-boolean atoms are written as strings.

## Decoding

Decoding is guided by the struct's defaults: a nested struct default decodes the nested
object into that struct, a concept default re-wraps the value, a date default parses the
string. An integer default receives an integer when the kernel returned a whole-number
float (`160.0` becomes `160`). Fields that hold a list of structs, or a struct that defaults
to `nil`, are declared with the optional `types:` option of `use Chronicle.Events.EventType`
and `use Chronicle.ReadModels.ReadModel`:

    use Chronicle.Events.EventType,
      id: "order-placed",
      types: [lines: {:list, MyApp.OrderLine}, address: MyApp.Address, labels: :map]

# `style`

```elixir
@type style() :: :camel | :identity
```

# `decode`

```elixir
@spec decode(module(), String.t() | map(), style()) :: struct() | nil
```

Decodes a JSON string or an already decoded map into `module`.

Unknown keys are ignored. Returns the struct, or `nil` when the JSON is invalid.

# `encode`

```elixir
@spec encode(term(), style()) :: term()
```

Converts a struct (or any term) to a JSON-encodable term using `style` for field names.

# `field_types`

```elixir
@spec field_types(module()) :: %{required(atom()) =&gt; term()}
```

Returns the declared field type hints of a struct module (see the moduledoc).

# `snake_case`

```elixir
@spec snake_case(String.t()) :: String.t()
```

Converts `camelCase`/`PascalCase` to `snake_case`.

# `to_json`

```elixir
@spec to_json(term(), style()) :: String.t()
```

Encodes a struct (or any term) to a JSON string.

# `wire_key`

```elixir
@spec wire_key(atom() | String.t(), style()) :: String.t()
```

Renders a struct field name using `style`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
