# Key-value text parser

Parse messy key: value or key=value text into JSON, grouping repeated keys, splitting blank-line records, and preserving ordered pairs with line numbers.

## Run it

- **CLI:** `gizza tool keyvalue-text-parser "Name: Ada Lovelace
Role = engineer
tag: math
tag: computing"`
- **Web:** https://gizza.ai/tools/keyvalue-text-parser/
- **Agents:** machine-readable descriptor (parameters JSON Schema) at https://gizza.ai/tools/keyvalue-text-parser/tool.json

## Inputs

- `input` — Key-value text _(field)_
- `separator` — Separator _(field)_
- `custom_separator` — Custom separator _(field)_
- `structure` — Output shape _(field)_
- `duplicates` — Duplicate keys _(field)_
- `trim` — Trim whitespace around keys and values _(field)_
- `unquote` — Remove matching quotes around values _(field)_
- `comment_prefixes` — Comment prefixes _(field)_
- `infer_types` — Infer booleans, nulls and numbers _(field)_
- `key_case` — Key case _(field)_
- `unmatched` — Lines without a separator _(field)_
- `indent` — Indent spaces _(field)_

## Output

- JSON output (text)

## Query parameters

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

- `input` — Key-value text
- `separator` — Separator
- `custom_separator` — Custom separator
- `structure` — Output shape
- `duplicates` — Duplicate keys
- `trim` — Trim whitespace around keys and values
- `unquote` — Remove matching quotes around values
- `comment_prefixes` — Comment prefixes
- `infer_types` — Infer booleans, nulls and numbers
- `key_case` — Key case
- `unmatched` — Lines without a separator
- `indent` — Indent spaces

Example: `https://gizza.ai/tools/keyvalue-text-parser/?input=Name%3A%20Ada%20Lovelace%0ARole%20%3D%20engineer%0Atag%3A%20math%0Atag%3A%20computing&separator=auto&custom_separator=-%3E&structure=object&duplicates=group&trim=true&unquote=true&comment_prefixes=%23%2C%3B%2C%2F%2F&infer_types=true&key_case=as-is&unmatched=skip&indent=2`

---

## About this tool

Key-value text shows up everywhere: pasted HTTP headers, form exports, scan metadata, support tickets, email snippets, invoice notes, and configuration fragments. They are easy for humans to read but annoying to feed into scripts because each source chooses its own separator, repeats fields in different ways, and mixes useful lines with headings or comments.

This parser turns that messy text into JSON. It understands `key: value`, `key=value`, tab-separated rows, pipes, or a custom separator like `->`. By default it skips prose lines, trims whitespace, removes one matching pair of quotes around values, and groups repeated keys into arrays so information is not silently overwritten.

Choose **records** when blank lines separate people, products, or tickets. Choose **pairs** when order and source line numbers matter more than a folded object. Turn on type inference only when you want unquoted `true`, `false`, `null`, and safe numbers to become real JSON values — IDs with leading zeros stay strings.

### Worked example

Input:

```text
Title: Quarterly report
Owner: Ada
tag: finance
tag: draft
Reviewed = false
```

With duplicate grouping, `snake_case` keys, and type inference enabled, output is:

```json
{
  "title": "Quarterly report",
  "owner": "Ada",
  "tag": [
    "finance",
    "draft"
  ],
  "reviewed": false
}
```

For multiple records, put a blank line between blocks:

```text
name: Ada
role: engineer

name: Grace
role: admiral
```

and select **Blank-line records** to get:

```json
[
  {
    "name": "Ada",
    "role": "engineer"
  },
  {
    "name": "Grace",
    "role": "admiral"
  }
]
```

## Options and limits

- Up to 10,000 input lines per run.
- `auto` separator uses whichever of `:` or `=` appears first on each line, so URLs such as `https://example.test/a=b` stay in the value when the first separator is the colon after the key.
- Duplicate-key policies are `group`, `last`, `first`, and `error`.
- Comment prefixes are comma-separated and match after leading whitespace. The default skips lines beginning with `#`, `;`, or `//`.
- Type inference is conservative: leading-zero IDs and `+15551234`-style phone numbers remain strings.
- The parser is line-oriented. It does not try to parse full YAML, TOML, INI sections, quoted multiline values, or nested objects.

## FAQ

<details>
<summary>How is this different from a YAML or TOML parser?</summary>

YAML, TOML, and INI parsers expect a formal file format. This tool is for loose pasted text where some lines are headings, some are comments, and the same key may appear several times. It extracts the simple `key separator value` lines and makes a predictable JSON object, record array, or pair list.

</details>

<details>
<summary>What happens when the same key appears more than once?</summary>

The default is to group repeated keys into an array in the order they appeared, so `tag: finance` followed by `tag: draft` becomes `"tag": ["finance", "draft"]`. You can instead keep the first value, keep the last value, or fail with an error on the duplicate line.

</details>

<details>
<summary>When should I use records instead of object output?</summary>

Use records when blank lines separate repeated entities, such as people, tickets, products, or scanned documents. Each block becomes its own JSON object. If your input is one continuous block, object output is simpler.

</details>

<details>
<summary>Does type inference change IDs or phone numbers?</summary>

It only converts values that are clearly safe: booleans, null-like words, and ordinary numbers. Values with leading zeros or a leading plus sign stay strings so ZIP codes, IDs, and phone numbers are not damaged.

</details>

<details>
<summary>Can I preserve every original line?</summary>

Choose **Ordered pairs with line numbers**. That output shape keeps one `{ "key", "value", "line" }` object per parsed pair, preserving order and source line numbers. Lines without separators are still skipped unless you set unmatched lines to error.

</details>

## Related tools

- [Identify a data sample's format, delimiter and columns](https://gizza.ai/tools/data-format-sniffer/): Paste a data sample and find out what it is: CSV, TSV, JSON, JSON Lines, XML, HTML, fixed-width or binary, plus delimiter, quote char, encoding and column types.
- [DynamoDB JSON Converter](https://gizza.ai/tools/dynamodb-json-converter/): Convert between DynamoDB typed AttributeValue JSON and plain JSON in both directions, with auto-detect and pretty or compact output.
- [Elasticsearch Bulk Formatter](https://gizza.ai/tools/elasticsearch-bulk-formatter/): Build a compact Elasticsearch _bulk API body from a JSON array. Choose index/create/update/delete, _index, _id field, and doc_as_upsert locally.
- [Convert stringified JSON values back to real types](https://gizza.ai/tools/json-coerce-types/): Paste JSON where every value is quoted and get real types back: numbers, booleans and nulls. Protects ZIP codes, big integers and chosen keys.
- [Format and filter structured JSON logs](https://gizza.ai/tools/json-log-formatter/): Pretty-print JSON log lines, flatten nested fields, filter by level or field, and export readable logs as text, table, JSON, or CSV.
