# `A2UICore.KeyOrder`
[🔗](https://github.com/a2ui-elixir/a2ui/blob/v0.1.1/umbrella/apps/a2ui_core/lib/a2ui_core/key_order.ex#L1)

JSON values whose objects keep their key order, as
`Jason.OrderedObject`s, for writing a document in a given order:
`Jason.encode!/1` writes an ordered object's keys in order, and a
map's in the map's own order.

    iex> template = Jason.decode!(~s({"b": 1, "a": 2}), objects: :ordered_objects)
    iex> %{"a" => 1, "b" => 2, "c" => 3} |> A2UICore.KeyOrder.like(template) |> Jason.encode!()
    ~s({"b":2,"a":1,"c":3})

The functions that change an ordered object follow a JSON object built
up in insertion order: `put/3` replaces a key's value where it stands
and adds a new key last.

# `delete`
*since 0.1.0* 

```elixir
@spec delete(Jason.OrderedObject.t(), String.t()) :: Jason.OrderedObject.t()
@spec delete(map(), String.t()) :: map()
```

Removes `key` from an ordered object or map.

# `empty?`
*since 0.1.0* 

```elixir
@spec empty?(Jason.OrderedObject.t() | map()) :: boolean()
```

Whether an ordered object or map has no keys.

# `get`
*since 0.1.0* 

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

The value of `key` in an ordered object or map, or `nil`.

# `has_key?`
*since 0.1.0* 

```elixir
@spec has_key?(term(), String.t()) :: boolean()
```

Whether an ordered object or map has `key`.

# `like`
*since 0.1.0* 

```elixir
@spec like(term(), term()) :: term()
```

`value` with each map ordered like the object at the same place in
`template` (an ordered object, or `nil` for none): first the keys the
template has, in its order, then the others, sorted. Lists follow a
template list item by item when both have the same length; otherwise
each item follows a template item equal to it. Ordered objects in
`value` keep their order.

# `message`
*since 0.1.0* 

```elixir
@spec message(term()) :: term()
```

An agent-to-renderer message as an ordered object, its keys in the
order the protocol's schemas list them, which is also the order a
model is shown and writes them: `version` first, then the message;
in its body `surfaceId` first and the components and data last; in a
component `id` and `component` first. Other keys follow, sorted. Data
values and ordered objects keep their order; anything but a map is
returned as it is.

A streaming reader can only act on a message once its `surfaceId` has
arrived, so this order lets a surface build while its message streams.

    iex> %{"updateComponents" => %{"components" => [], "surfaceId" => "s"}, "version" => "v1.0"}
    ...> |> A2UICore.KeyOrder.message()
    ...> |> Jason.encode!()
    ~s({"version":"v1.0","updateComponents":{"surfaceId":"s","components":[]}})

# `new`
*since 0.1.0* 

```elixir
@spec new([{String.t(), term()}]) :: Jason.OrderedObject.t()
```

An ordered object holding `pairs`, in their order.

# `put`
*since 0.1.0* 

```elixir
@spec put(Jason.OrderedObject.t(), String.t(), term()) :: Jason.OrderedObject.t()
@spec put(map(), String.t(), term()) :: map()
```

Sets `key` to `value`: in place when the object has the key, else as
its last key. A map is updated with `Map.put/3`.

# `put_new`
*since 0.1.0* 

```elixir
@spec put_new(Jason.OrderedObject.t(), String.t(), term()) :: Jason.OrderedObject.t()
```

Sets `key` to `value` unless the object has the key.

# `to_plain`
*since 0.1.0* 

```elixir
@spec to_plain(term()) :: term()
```

`term` with its ordered objects turned into maps.

---

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