API reference

Convert YAML to JSON

Convert YAML to JSON under pinned YAML 1.2 core-schema rules, with line/column errors and YAML 1.1 pitfall warnings.

GET POST /api/convert/yaml-to-json MCP tool yaml_to_json

Parses input as YAML 1.2 with the core schema, whatever any %YAML directive says, so yes/no/on/off are strings, 0755 is the decimal 755, and dates stay strings; each such value gets a warning because YAML 1.1 parsers read them differently. Duplicate keys are an error. Aliases are expanded, with at most 1,000 expansions and 200,000 output values (billion-laughs protection); recursive aliases are an error. << merge keys are applied unless merge_keys is false. .inf/.nan and complex (collection) keys are errors; non-string scalar keys become strings with a warning. Tags outside the core schema (!!binary, !!timestamp, !Ref, …) follow custom_tags. Errors give line, column and code.

Browser version (runs locally): YAML Format & Validate.

Try it

Credentials
Remember these credentials

Not saved: you will paste them again next time.

No credentials yet? Get a client ID and secret. They are sent only to this site, in an Authorization: Basic header.

POST /api/convert/yaml-to-json with a JSON body

Parameters

Parameter Type Default Description
input required string (≤ 30000 chars) — The YAML text, as a string field or a raw text/plain POST body.
documents first | all first first converts the first document (with a warning if there are more; no documents gives null). all returns a JSON array with one element per document.
indent 2 | 4 | tab | none 2 JSON output indentation: 2 or 4 spaces, tab, or none for minified output (no whitespace at all).
sort_keys boolean false Sort object keys recursively, by UTF-16 code units (the order RFC 8785 uses). Array order never changes.
merge_keys boolean true Apply << merge keys (YAML 1.1 feature, common in Compose and CI files). false keeps << as an ordinary key.
custom_tags error | drop | wrap error Values with a tag outside the core schema: error rejects them; drop keeps the value and discards the tag; wrap produces {"<tag>": value}, e.g. {"!Ref": "MyBucket"}.

Also accepted on every endpoint: format (json | text). Parameters may come from the query string, a JSON object body, an urlencoded or multipart form, or (for input) a text/plain body.

Global parameters
Parameter Type Default Description
format json | text json json returns the documented object. text returns only the primary value as text/plain (see "Text output").

Response 200 application/json

Field Type Description
json string The JSON text, formatted per indent.
value any The same data as a JSON value.
documentCount integer Number of YAML documents in the input.
warnings array of object YAML 1.1/1.2 ambiguities, converted keys, extra documents, large integers. At most 100 are listed.
warnings[].message string Plain-language finding.
warnings[].line integer 1-based line number.
warnings[].column integer 1-based column, counted in Unicode code points.
warnings[].pointer string JSON Pointer of the value in the output.

Text output (format=text, text/plain): The JSON text.

Errors

Errors are JSON: {"error": "<message>", "code": "<code>", "param": "<name>"?}.

Status Code When
422 unprocessable_input The YAML does not parse (the message gives line, column and the library error code), has duplicate keys, uses a value with no JSON equivalent, a custom tag with custom_tags=error, a recursive alias, or exceeds the alias or size limits.
400 invalid_parameter input is longer than 30,000 characters (YAML parsing is the slowest step; use the page for larger files), or an option is not a listed value.
400 missing_parameter A required parameter is absent.
400 unknown_parameter A parameter name is not in the table above (typos are rejected, not ignored).
413 payload_too_large The request body exceeds 1 MiB.
405 method_not_allowed A method other than GET, POST or OPTIONS.

Behaviour

  • Idempotent: the same arguments always return the same result.
  • Requires a client ID and secret (authentication). Each call is recorded as one metadata row against your client ID; inputs and outputs are never stored or logged. Responses carry cache-control: no-store.
  • CORS: any origin may call this endpoint from a browser, using your credentials.

Examples

Responses below were produced by running each request through this code at build time. Long strings are shortened.

YAML 1.1 pitfalls, anchors and a merge key

curl -X POST 'https://util.caruana.me/api/convert/yaml-to-json' \
  -H 'content-type: application/json' \
  -d '{"input":"defaults: &defaults\n  retries: 3\n  country: no\nservice:\n  <<: *defaults\n  mode: 0755\n  port: 8080\n"}'

Response 200

{
  "json": "{\n  \"defaults\": {\n    \"retries\": 3,\n    \"country\": \"no\"\n  },\n  \"service\": {\n    \"retries\": 3,\n    \"country\": \"no\",\n    \"mode\": 755,\n    \"port\": 8080\n  }\n}",
  "value": {
    "defaults": {
      "retries": 3,
      "country": "no"
    },
    "service": {
      "retries": 3,
      "country": "no",
      "mode": 755,
      "port": 8080
    }
  },
  "documentCount": 1,
  "warnings": [
    {
      "message": "no is the string \"no\" in YAML 1.2, but YAML 1.1 parsers read it as a boolean. Quote it to be unambiguous.",
      "line": 3,
      "column": 12,
      "pointer": "/defaults/country"
    },
    {
      "message": "no is the string \"no\" in YAML 1.2, but YAML 1.1 parsers read it as a boolean. Quote it to be unambiguous.",
      "line": 3,
      "column": 12,
      "pointer": "/service/country"
    },
    {
      "message": "0755 is the decimal integer 755 in YAML 1.2, but YAML 1.1 parsers read a leading 0 as octal (493). Write 0o755 for octal, or quote it for a string.",
      "line": 6,
      "column": 9,
      "pointer": "/service/mode"
    }
  ]
}
Same call as an MCP tools/call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "yaml_to_json",
    "arguments": {
      "input": "defaults: &defaults\n  retries: 3\n  country: no\nservice:\n  <<: *defaults\n  mode: 0755\n  port: 8080\n"
    }
  }
}

Several documents

curl -X POST 'https://util.caruana.me/api/convert/yaml-to-json' \
  -H 'content-type: application/json' \
  -d '{"input":"name: a\n---\nname: b\n","documents":"all","indent":"none"}'

Response 200

{
  "json": "[{\"name\":\"a\"},{\"name\":\"b\"}]",
  "value": [
    {
      "name": "a"
    },
    {
      "name": "b"
    }
  ],
  "documentCount": 2,
  "warnings": []
}
Same call as an MCP tools/call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "yaml_to_json",
    "arguments": {
      "input": "name: a\n---\nname: b\n",
      "documents": "all",
      "indent": "none"
    }
  }
}

CloudFormation-style tags, wrapped

curl -X POST 'https://util.caruana.me/api/convert/yaml-to-json' \
  -H 'content-type: application/json' \
  -d '{"input":"Bucket: !Ref MyBucket\nArn: !GetAtt [MyBucket, Arn]\n","custom_tags":"wrap"}'

Response 200

{
  "json": "{\n  \"Bucket\": {\n    \"!Ref\": \"MyBucket\"\n  },\n  \"Arn\": {\n    \"!GetAtt\": [\n      \"MyBucket\",\n      \"Arn\"\n    ]\n  }\n}",
  "value": {
    "Bucket": {
      "!Ref": "MyBucket"
    },
    "Arn": {
      "!GetAtt": [
        "MyBucket",
        "Arn"
      ]
    }
  },
  "documentCount": 1,
  "warnings": []
}
Same call as an MCP tools/call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "yaml_to_json",
    "arguments": {
      "input": "Bucket: !Ref MyBucket\nArn: !GetAtt [MyBucket, Arn]\n",
      "custom_tags": "wrap"
    }
  }
}