# `Digger`
[🔗](https://github.com/treble37/digger/blob/v3.3.0/lib/protocols/digger_protocol.ex#L1)

Documentation for Digger Protocol

# `t`

```elixir
@type t() :: term()
```

All the types that implement this protocol.

# `atomize`

```elixir
@spec atomize(
  Digger.Types.data_type(),
  keyword()
) :: Digger.Types.valid_return_type()
```

'Atomize' a valid Types.data_type according to the protocol implementation

By default, atomizing a string that has no corresponding existing atom
creates a new one via `String.to_atom/1`, which is safe for trusted input
but can exhaust the atom table if used on untrusted/external data (atoms
are never garbage collected).

Pass `existing: true` to atomize via `String.to_existing_atom/1` instead:
strings that already have a matching atom are converted as usual, and
strings that don't are left as the original string rather than raising or
creating a new atom.

## Examples

    iex> Digger.atomize(%{"user" => %{"name" => "Ada"}})
    %{user: %{name: "Ada"}}

    iex> Digger.atomize(%{"ok" => 1, "no_such_atom_xyz" => 2}, existing: true)
    %{:ok => 1, "no_such_atom_xyz" => 2}

# `camel_case`

```elixir
@spec camel_case(
  Digger.Types.data_type(),
  keyword()
) :: Digger.Types.valid_return_type()
```

Camel case a valid Types.data_type according to the protocol implementation

The default is UpperCamelCase; pass `key_transform: :lower` for the
lowerCamelCase convention used in JavaScript APIs.

## Examples

    iex> Digger.camel_case(%{user_id: 1})
    %{UserId: 1}

    iex> Digger.camel_case(
    ...>   %{user_id: 1},
    ...>   type: :key, key_transform: :lower, value_transform: :none
    ...> )
    %{userId: 1}

# `dasherize`

```elixir
@spec dasherize(
  Digger.Types.data_type(),
  keyword()
) :: Digger.Types.valid_return_type()
```

'Dasherize' a valid Types.data_type according to the protocol implementation

## Examples

    iex> Digger.dasherize(%{"foo_bar" => 1})
    %{"foo-bar" => 1}

# `flatten`

```elixir
@spec flatten(
  Digger.Types.data_type(),
  keyword()
) :: Digger.Types.valid_return_type()
```

Flatten a nested map into a single-level map whose keys are the
separator-joined paths (default separator `"."`) to each leaf value

Path keys are converted to strings with `to_string/1`, so keys must
implement `String.Chars` (atoms, strings, and numbers all do).
Structs (including calendar types like `Date`), lists, and empty maps
are leaf values — they are never descended into. Non-map input passes
through unchanged.

## Examples

    iex> Digger.flatten(%{a: %{b: 1}})
    %{"a.b" => 1}

    iex> Digger.flatten(%{"user" => %{"id" => 7}}, separator: "/")
    %{"user/id" => 7}

# `lowercase_first`

```elixir
@spec lowercase_first(
  Digger.Types.data_type(),
  keyword()
) :: Digger.Types.valid_return_type()
```

Lower case first letter of a valid Types.data_type according to the protocol implementation

## Examples

    iex> Digger.lowercase_first(%{"FooBar" => 1})
    %{"fooBar" => 1}

# `snake_case`

```elixir
@spec snake_case(
  Digger.Types.data_type(),
  keyword()
) :: Digger.Types.valid_return_type()
```

snake_case a valid Types.data_type according to the protocol implementation

Only keys are transformed by default — string values pass through
unchanged.

## Examples

    iex> Digger.snake_case(%{"userId" => 1, "displayName" => "johnDoe"})
    %{"user_id" => 1, "display_name" => "johnDoe"}

# `stringify`

```elixir
@spec stringify(
  Digger.Types.data_type(),
  keyword()
) :: Digger.Types.valid_return_type()
```

'Stringify' a valid Types.data_type according to the protocol implementation

## Examples

    iex> Digger.stringify(%{user: %{name: "Ada"}})
    %{"user" => %{"name" => "Ada"}}

# `unflatten`

```elixir
@spec unflatten(
  Digger.Types.data_type(),
  keyword()
) :: Digger.Types.valid_return_type()
```

Rebuild a nested map from a flattened one by splitting each string key
on the separator (default `"."`)

The exact inverse of `Digger.flatten/2` for the maps it produces:
`unflatten(flatten(map)) == map` whenever `map`'s keys are strings
that don't contain the separator. Maps with atom or number keys
round-trip to their string-keyed equivalent, since `flatten/2`
converts path keys to strings. Non-string keys are kept in place,
never split. Non-map input passes through unchanged.

## Examples

    iex> Digger.unflatten(%{"a.b" => 1, "a.c" => 2})
    %{"a" => %{"b" => 1, "c" => 2}}

    iex> Digger.unflatten(%{"user/id" => 7}, separator: "/")
    %{"user" => %{"id" => 7}}

# `upcase_first`

```elixir
@spec upcase_first(
  Digger.Types.data_type(),
  keyword()
) :: Digger.Types.valid_return_type()
```

Upper case the first letter of a valid Types.data_type according to
the protocol implementation

## Examples

    iex> Digger.upcase_first(%{"fooBar" => 1})
    %{"FooBar" => 1}

---

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