# On-Demand API

Lazy, forward-only iteration, decoding values only when accessed, without building a tree.


The On-Demand API decodes values lazily as you touch them. Nothing builds a full
tree, so it's faster and allocates far less than the [DOM](../dom/), at the
cost of forward-only access.

## Iterating

`iterate` returns a `JsonDocument`. Walk it in document order:

```kotlin
val json: ByteArray = loadTwitterJson()

SimdJsonParser().use { parser ->
    parser.iterate(json).use { doc ->
        for (tweet in doc.getObject()["statuses"].getArray()) {
            val user = tweet.getObject()["user"].getObject()
            if (user["default_profile"].getBoolean()) {
                println(user["screen_name"].getString())
            }
        }
    }
}
```

## Reading values

Navigate with `getObject()` / `getArray()`, then pull scalars with the typed
getters:

<table class="kt-params">
  <thead>
    <tr><th>Parameter</th><th>Description</th></tr>
  </thead>
  <tbody><tr>
          <td>
            <code class="kt-params__name">JsonDocument</code><span class="kt-params__type">AutoCloseable</span></td>
          <td>Root value: <code>getObject()</code>, <code>getArray()</code>, <code>getString()</code>, <code>getLong()</code>, <code>getULong()</code>, <code>getDouble()</code>, <code>getBoolean()</code>, <code>isNull()</code>, <code>getType()</code>.</td>
        </tr><tr>
          <td>
            <code class="kt-params__name">OnDemandObject</code><span class="kt-params__type">Iterable&lt;OnDemandField&gt;</span></td>
          <td>Forward-only object. <code>obj[&quot;field&quot;]</code> and <code>obj.findField(&quot;field&quot;)</code> both return an <code>OnDemandValue</code>.</td>
        </tr><tr>
          <td>
            <code class="kt-params__name">OnDemandArray</code><span class="kt-params__type">Iterable&lt;OnDemandValue&gt;</span></td>
          <td>Forward-only array. Iterate to read its elements.</td>
        </tr><tr>
          <td>
            <code class="kt-params__name">OnDemandValue</code><span class="kt-params__type">AutoCloseable</span></td>
          <td>A not-yet-decoded value: the same typed getters as <code>JsonDocument</code>, plus <code>materialize()</code>.</td>
        </tr><tr>
          <td>
            <code class="kt-params__name">OnDemandField</code><span class="kt-params__type">—</span></td>
          <td>A single object entry: <code>name</code> and <code>value</code>.</td>
        </tr></tbody>
</table>


Need a random-access snapshot of a subtree? `OnDemandValue.materialize()` decodes
it into a DOM [`JsonValue`](../dom/#the-jsonvalue-tree):

```kotlin
val user: JsonValue = tweet.getObject()["user"].materialize()
```

## Forward-only rules

On-Demand trades random access for speed. Three rules follow from that:

<aside class="kt-callout kt-callout--important">
  <svg class="kt-callout__icon" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 2 4 5v6c0 5 3.5 9 8 11 4.5-2 8-6 8-11V5l-8-3z"/><path d="M12 8v4"/><path d="M12 16h.01"/></svg>
  <div class="kt-callout__body"><strong class="kt-callout__title">Consume in order, once</strong><div class="kt-callout__content"><ul>
<li>Read fields and elements in the order they appear in the document.</li>
<li>An object or array is <strong>consumed by iterating it</strong>, so iterate it only once.</li>
<li>Finish with a value before moving on to its sibling.</li>
</ul>
<p>Breaking these throws a <code>JsonIterationException</code>. When a typed getter meets the
wrong JSON type (e.g. <code>getString()</code> on a number) you get a <code>JsonTypeException</code>
carrying the <code>expected</code> and <code>actual</code> types.</p></div>
  </div>
</aside>


## Lifecycle

The `JsonDocument`, and every value it yields, live on the parser's buffers, so
close the document when you're done. `iterate(json).use { doc -> … }` does that,
and closing the parser closes everything under it. Both are `AutoCloseable`.

## DOM or On-Demand?

| Reach for… | When |
|---|---|
| **On-Demand** | You read each field once, in order, and want the lowest latency and allocation. |
| **DOM** | You need random access, multiple passes, or want to keep values after the parser closes. |
| **[Serialization](../serialization/)** | You're on the JVM and want to decode straight into `@Serializable` classes. |
