# `TypeSafeAPI.JSON.OrderedObject`
[🔗](https://github.com/typesend/typesafe_ai/blob/v0.1.0-alpha.3/lib/typesafe_api/json/ordered_object.ex#L1)

A JSON object that encodes its pairs in the order given.

Elixir maps do not preserve insertion order at any size. The API treats a
Choice question's `criteria` as an ordered list of options (the order is
what the model sees), so Choice criteria travel as this struct rather than
as a map.

    JSON.encode!(%TypeSafeAPI.JSON.OrderedObject{pairs: [{"b", 1}, {"a", nil}]})
    #=> ~s({"b":1,"a":null})

Keys must be atoms or strings, and `new/1` says so at construction rather
than letting a bad key surface from inside the encoder at request time.
Values may be anything `JSON` can encode.

## It is not a map

This is a struct, so `is_map/1` returns `true` for it and `map_size/1`
returns its field count, not its pair count. Anything that inspects a wire
object generically should use `Enum` instead: the struct implements
`Enumerable` over its `{key, value}` pairs, so `Enum.count/1`,
`Enum.map/2` and `Enum.into/2` all work and see the pairs in order.

    object = TypeSafeAPI.JSON.OrderedObject.new([{"b", 1}, {"a", 2}])
    Enum.count(object)   #=> 2
    Enum.into(object, %{}) #=> %{"a" => 2, "b" => 1}

# `t`

```elixir
@type t() :: %TypeSafeAPI.JSON.OrderedObject{pairs: [{atom() | String.t(), term()}]}
```

# `new`

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

Wraps a list of `{key, value}` pairs.

Raises `ArgumentError` for an element that is not a two-element tuple, or a
key that is not an atom or a string.

---

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