# YAML to CSV

Flatten a YAML list or mapping of records into CSV with a unioned column header. Nested keys become dot-paths. Runs in your browser, no upload.

## Run it

- **CLI:** `gizza tool yaml-to-csv "alice:
  age: 30
  city: Paris
bob:
  age: 40
  city: Berlin"`
- **Web:** https://gizza.ai/tools/yaml-to-csv/
- **Agents:** machine-readable descriptor (parameters JSON Schema) at https://gizza.ai/tools/yaml-to-csv/tool.json

## Inputs

- `data` — YAML _(field)_
- `delimiter` — Delimiter _(field)_
- `header` — Include header row _(field)_
- `array_mode` — Array handling _(field)_
- `quote_all` — Quote every field _(field)_
- `key_column` — Mapping key column name _(field)_

## Output

- CSV (text)

## Query parameters

Open the tool pre-filled and auto-run via URL:

- `data` — YAML
- `delimiter` — Delimiter
- `header` — Include header row
- `array_mode` — Array handling
- `quote_all` — Quote every field
- `key_column` — Mapping key column name

Example: `https://gizza.ai/tools/yaml-to-csv/?data=alice%3A%0A%20%20age%3A%2030%0A%20%20city%3A%20Paris%0Abob%3A%0A%20%20age%3A%2040%0A%20%20city%3A%20Berlin&delimiter=comma&header=true&array_mode=json&quote_all=true&key_column=key`

---

## What this tool does

Turn a block of **YAML** into a **CSV** table you can open in a spreadsheet.
Paste a top-level **list of records**, or a **mapping** whose values are records,
and every record becomes one row. The header is the **union of every record's
keys**, in the order they are first seen, so rows that are missing a field simply
leave that cell blank instead of shifting columns. Nested mappings are flattened
to **dot-path** columns (`address.city`), and arrays are rendered the way you
choose. Everything runs in your browser — the YAML never leaves your device.

## How the shape is read

- **A list of records** — the common case. Each list item is a row:

  ```yaml
  - name: Ada
    age: 36
    address:
      city: London
  - name: Bo
    age: 40
  ```

  becomes `name,address.city,age` with one row per person.

- **A mapping of records** — when the top level is a mapping whose values are
  themselves records, each entry is a row and its key is kept in an extra column
  (named by **Mapping key column name**, `key` by default):

  ```yaml
  alice:
    age: 30
  bob:
    age: 40
  ```

  becomes `key,age` / `alice,30` / `bob,40`.

- **A single record** — a top-level mapping whose values are all scalars is
  treated as one row (no key column).

## Options

- **Delimiter** — separate columns with a comma, semicolon, tab, or pipe.
- **Include header row** — turn off to emit data rows only.
- **Array handling** — `json` writes an array as one compact JSON string in a
  single cell (`["a","b"]`); `joined` joins a scalar array with `, ` in one cell;
  `columns` expands each element into its own dot-indexed column (`tags.0`,
  `tags.1`).
- **Quote every field** — wrap all cells in double quotes, not just the ones that
  contain a delimiter, quote, or newline.
- **Mapping key column name** — the header for the key column when the input is a
  mapping of records; leave it blank to drop the key.

## Limits

- The whole document is parsed in memory, so extremely large files (tens of MB)
  may be slow in a browser tab.
- Only the **top level** decides the shape: a list of records, a mapping of
  records, or a single scalar mapping. A top-level scalar, or a top-level list of
  scalars, has no columns and is reported as an unsupported shape.
- Deeply nested mappings flatten to dot-paths; if two different structures
  produce the same dot-path, the later value wins.
- YAML anchors/aliases are expanded by the parser; custom `!tags` are dropped and
  only their value is kept.

## FAQ

<details>
<summary>Is my data uploaded anywhere?</summary>

No. The conversion runs entirely in your browser with WebAssembly, so the YAML
you paste never leaves your device and the tool keeps working offline once the
page has loaded.

</details>

<details>
<summary>What happens when records don't all have the same keys?</summary>

The header is the **union** of every record's keys, in first-seen order. A record
that is missing a key just gets an empty cell for that column, so columns never
shift out of alignment.

</details>

<details>
<summary>How are nested objects and arrays handled?</summary>

Nested mappings are flattened to dot-path columns — `address: {city: London}`
becomes a column named `address.city`. Arrays follow the **Array handling**
option: kept as a compact JSON string, joined into one cell, or expanded into
`name.0`, `name.1` columns.

</details>

<details>
<summary>Which delimiters and quoting rules are used?</summary>

Pick comma, semicolon, tab, or pipe as the delimiter. Fields are quoted only when
they contain the delimiter, a double quote, or a newline (embedded quotes are
doubled), following the usual CSV rules — or turn on **Quote every field** to
quote everything.

</details>

<details>
<summary>Why do I get an "unsupported top-level YAML shape" error?</summary>

The converter needs records to build columns from. A top-level list of records or
a mapping of records works; a bare scalar (`just a string`) or a list of plain
scalars has no fields to become columns, so it is rejected with a clear message.

</details>

## Related tools

- [Amazon Order Analyzer](https://gizza.ai/tools/amazon-order-analyzer/): Paste an Amazon order-history CSV export to summarize total spend by month, top items, and category breakdowns. Browser-only, private, with Markdown or JSON output.
- [Avro to JSON Converter](https://gizza.ai/tools/avro-to-json/): Decode Apache Avro Object Container Files (.avro / OCF) to JSON, NDJSON, or the embedded schema — no .avsc needed, free and private in your browser.
- [Reconcile bank statement and ledger CSVs](https://gizza.ai/tools/bank-statement-reconcile/): Match bank-statement CSV rows to ledger rows by date, signed amount, and fuzzy memo similarity, with unmatched and suggested matches.
- [Bencode decoder](https://gizza.ai/tools/bencode-decoder/): Decode bencode (the BitTorrent / .torrent serialization format) into readable JSON, and re-encode JSON back into canonical bencode — in your browser. Nothing is uploaded.
- [Budget Planner](https://gizza.ai/tools/budget-planner/): Plan a monthly budget from take-home pay: 50/30/20 needs/wants/savings targets with custom splits, or a zero-based plan showing what's left to allocate.
