JSON to YAML Converter - The Complete Guide for Developers

Rahmat Ullah profile photoRahmat Ullah
10 min readDeveloper Tools, DevOps, Data Formats

Last month I was handed an OpenAPI spec as a 1,400 line JSON file and asked to drop it into a Helm chart that expected YAML. I copied the JSON into the first online converter I found, pasted the output into my values file, and the chart promptly refused to render. The keys had been reordered alphabetically, my version string "1.10" had silently become the float 1.1, and a phone number with a leading zero had turned into an octal. Going from JSON to YAML sounds like a one-click problem, but the round trip can quietly mangle your data if you do not know what to look for.

JSON and YAML cover the same conceptual ground - they both store structured data with strings, numbers, booleans, lists, and nested objects. So in theory, converting between them should be lossless. In practice, going from JSON to YAML is the direction that catches most people off guard, because YAML offers more formatting freedom than JSON does, and the converter has to make choices on your behalf. If you just need to do the conversion right now, you can paste your JSON into the online JSON to YAML tool and have valid YAML in seconds. The rest of this post explains what is actually happening under the hood, so you can spot the cases where a quick paste is not enough. If you want a primer on how the two formats compare in general, the YAML to JSON converter guide covers the basics.

Real Reasons People Convert JSON to YAML

In day-to-day work I see four scenarios come up over and over. Each one involves data that started its life as JSON and now needs to live somewhere YAML is the expected format.

  • API responses going into Kubernetes ConfigMaps. Your service returns a JSON config blob, and you want to bake it into a ConfigMap or Secret manifest. Manifests are YAML, so the JSON has to be reshaped before kubectl will accept it.
  • package.json values flowing into Helm charts. You have a Node project with version numbers, image tags, and feature flags scattered across package.json. The Helm values file that deploys the app needs the same data, only formatted as YAML so DevOps engineers can read it.
  • OpenAPI specs handed off between teams. The backend team writes their OpenAPI spec in JSON because their tooling generates it that way. The docs team and the API gateway both prefer the YAML form. Conversion is the bridge.
  • Postman exports turned into test fixtures. Postman exports collections as JSON. If your integration tests run against fixtures stored as YAML so QA can edit them, you convert on import.

What ties these together is direction of travel. The data was born as JSON, often produced by a tool or another service, and now a human or a YAML-loving consumer needs to pick it up. The conversion is rarely the goal. It is a step that has to be invisible so the next person in the pipeline does not even notice.

What Actually Changes When You Convert

This is the part that surprised me when I first started doing this regularly. JSON is strict and unambiguous. There is exactly one way to represent {"port": 8080}. YAML is the opposite. The same value can be written in at least three different ways, and the converter you use will pick one for you.

Here is what shifts during the trip from JSON to YAML:

  • Quotes around strings often disappear. JSON wraps every string in double quotes. YAML lets most strings live unquoted. So "hostname" in JSON becomes hostname in YAML. Usually fine, but values like "yes", "no", "on", "off", or "null" need to stay quoted or YAML will reinterpret them as booleans or null on the next parse.
  • Numbers stay as numbers but lose any leading zeros. If your JSON had "phone": "0123" as a string, that survives. If it had "phone": 123 as a number, the YAML output will have phone: 123 and you cannot tell from the file whether the original was meant to be padded.
  • Arrays get flattened into dash lists. The JSON ["red", "green", "blue"] typically becomes a vertical list with each item on its own line. Some converters offer a flow style that keeps the inline form, but block style is the default.
  • Indentation appears where there was none. JSON does not care about whitespace. YAML cares about it deeply. Two-space indentation is the most common output, but four-space and tab-based YAML exist in the wild.
  • Comments cannot be added back. JSON has no comments to begin with, so this is not really a loss, but worth noting if you were hoping the converter would inject helpful notes. It cannot. Comments need to be added by hand after conversion.

Watch out: If a JSON value is the string "true", "false", "null", or anything resembling a YAML reserved word, a careless converter will write it unquoted into the YAML output. The next parser to touch the file will read it as a boolean or null and your data is silently corrupted. Always check that string-typed values keep their quotes when they need to.

YAML Output Styles - Block, Flow, and Everything in Between

YAML has two main syntactic modes for representing collections, and a converter has to pick one. Most people only ever see block style output, but knowing both helps when you are debugging unexpected results.

Block style (the default)

Block style is the indentation-driven form everyone associates with YAML. Each key on its own line, each list item prefixed with a dash, nested structures pushed in by two spaces.

service:
  name: api-gateway
  replicas: 3
  ports:
    - 80
    - 443
  env:
    LOG_LEVEL: info
    REGION: us-east-1

Flow style (JSON-like)

Flow style keeps the curly braces and square brackets that JSON uses, just without the requirement for quotes around keys. It is compact but loses the readability advantage that pulled people toward YAML in the first place.

service: { name: api-gateway, replicas: 3, ports: [80, 443], env: { LOG_LEVEL: info, REGION: us-east-1 } }

You almost never want flow style for files humans will read. But it is useful for embedding small YAML snippets inside other documents, or for one-line config values where a multi-line block would feel out of place.

Mixed style

Most YAML libraries default to a sensible hybrid. Top-level structures get block style, while small leaf collections (a list of two or three items) sometimes get flow style to keep the file from sprawling vertically. Python's yaml.dump() exposes this as the default_flow_style parameter. Setting it to False forces pure block style, which is usually what you want for config files. Setting it to None lets the library decide per node.

Key Ordering and Why Yours Got Scrambled

JSON technically does not guarantee key order, but every modern parser preserves the order keys appeared in the source. So your JSON file with name first and port second tends to round-trip with that order intact through any pipeline.

YAML serializers historically defaulted to alphabetical key ordering. PyYAML is a famous offender here. If you load JSON into a Python dictionary and dump it with default settings, you get port before name in the output. For a flat config that is annoying. For a Kubernetes manifest where the order matters to humans reading the file, it is destructive.

The fix in Python is one parameter:

import json
import yaml

with open('input.json') as f:
    data = json.load(f)

with open('output.yaml', 'w') as f:
    yaml.dump(data, f, sort_keys=False, default_flow_style=False, indent=2)

The sort_keys=False setting tells PyYAML to emit keys in the order they appear in the dictionary, which (since Python 3.7) is insertion order. Most other languages have an equivalent option. In JavaScript's js-yaml it is sortKeys: false, which is actually the default. In Ruby's psych library, you have to use YAML.dump with care because the default tends to preserve order but document anchors can shift things.

Heads up: If you are seeing your keys come out alphabetized after a JSON to YAML conversion and you did not ask for that, it is almost always the YAML library defaulting to sort_keys=True. This is one of the most common surprises people hit, and it has nothing to do with the JSON side of the conversion.

Converting JSON to YAML in Code (Python, Node, Ruby, Go)

When the conversion needs to be part of a script, build step, or CI pipeline, doing it in code gives you control over all the formatting choices we just covered. Here are the patterns I use most.

Python with PyYAML

import json
import yaml

# Load JSON from a file or string
with open('config.json') as f:
    data = json.load(f)

# Dump as YAML with the settings that produce sane output
with open('config.yaml', 'w') as f:
    yaml.dump(
        data,
        f,
        sort_keys=False,
        default_flow_style=False,
        indent=2,
        width=120,
        allow_unicode=True
    )

The width=120 option stops PyYAML from wrapping long string values at 80 characters, which is usually what you want for config files. allow_unicode=True keeps non-ASCII characters as themselves rather than escaping them to \u sequences, which matters for filenames, labels, and any field that might contain accented characters or emoji.

Node.js with js-yaml

const fs = require('fs');
const yaml = require('js-yaml');

const json = JSON.parse(fs.readFileSync('config.json', 'utf8'));

const yamlOutput = yaml.dump(json, {
  indent: 2,
  lineWidth: 120,
  noRefs: true,
  sortKeys: false
});

fs.writeFileSync('config.yaml', yamlOutput);

The noRefs: true setting is worth flagging. By default, js-yaml will detect duplicate object references in your data and emit YAML anchors and aliases to deduplicate them. That is technically smaller output, but it confuses humans and breaks tools that do not handle anchors well. For interchange, turn refs off.

Ruby with psych (built in)

require 'json'
require 'yaml'

data = JSON.parse(File.read('config.json'))
File.write('config.yaml', data.to_yaml)

Ruby's psych library generally preserves key order from the source hash, so this almost always does the right thing without configuration. The output is block style with two-space indentation by default.

Go with gopkg.in/yaml.v3

package main

import (
    "encoding/json"
    "os"
    "gopkg.in/yaml.v3"
)

func main() {
    jsonBytes, _ := os.ReadFile("config.json")
    var data interface{}
    json.Unmarshal(jsonBytes, &data)

    yamlBytes, _ := yaml.Marshal(data)
    os.WriteFile("config.yaml", yamlBytes, 0644)
}

Go's yaml.v3 preserves map ordering when you decode into yaml.Node directly, but with interface{} the underlying map type does not guarantee order. If ordering matters, decode the JSON into a struct or into a yaml.Node tree and walk it manually.

CLI Conversion - yq, json2yaml, and One-Liners

For one-off conversions or shell pipelines, the command line beats writing a script every time. These are the tools I keep within reach.

yq (the Mike Farah version)

yq is the closest thing to a standard for command-line YAML manipulation. It happily reads JSON and emits YAML.

# Convert a JSON file to YAML
yq -P -o=yaml config.json > config.yaml

# Pipe in from another command
curl -s https://api.example.com/config | yq -P -o=yaml

# Combine with jq for filtering before converting
jq '.services.api' deployment.json | yq -P -o=yaml

The -P flag is shorthand for "pretty print" and gives you clean block-style output. Without it you sometimes get the flow style YAML that nobody wants to read.

Python one-liner (no installation if you have Python)

python3 -c "import sys, json, yaml; print(yaml.dump(json.load(sys.stdin), sort_keys=False, default_flow_style=False))" < config.json

Slightly verbose but it works on almost any machine that has Python and PyYAML installed. I have this aliased as j2y in my shell rc file because I use it constantly.

Ruby one-liner

ruby -ryaml -rjson -e 'puts JSON.parse(STDIN.read).to_yaml' < config.json

If you are on macOS or any modern Linux distribution, Ruby is usually preinstalled and this just works. No extra packages needed.

Pipeline tip: Combine jq and yq when you only need part of a JSON document in YAML form. jq '.spec.template' pod.json | yq -P -o=yaml > template.yaml extracts just the template section and writes it as a standalone YAML file. This pattern is gold for splitting big manifests into smaller files.

Using the StackConvert JSON to YAML Tool

When you do not want to think about library options, package installs, or shell flags, the StackConvert JSON to YAML converter handles the conversion in your browser with sensible defaults already applied.

  1. 1 Paste your JSON into the input panel on the left
  2. 2 The YAML output appears immediately on the right with key order preserved
  3. 3 If your JSON has a syntax error, the panel highlights what failed and where
  4. 4 Copy the YAML output with one click and drop it into your config file

The conversion runs entirely in your browser using JavaScript. Nothing leaves your machine, which matters when the JSON you are converting contains API tokens, database passwords, signing keys, or any other secret. I have used it on production Kubernetes secrets and Helm value files where uploading to a remote service was simply not an option.

If you ever need the reverse direction, the same engine handles it from the YAML to JSON converter page. And if your JSON is malformed before conversion, run it through the JSON formatter first to fix the syntax and pretty-print it. That two-step flow has saved me from writing converters for files that were broken before they ever became my problem.

Frequently Asked Questions

Why did my keys get reordered alphabetically?

The YAML library you used has sort_keys turned on by default. PyYAML, Go's yaml.v2, and a few other libraries do this. Pass sort_keys=False (or the equivalent for your language) to keep the original order. Online converters that produce alphabetized output usually have no toggle, so if order matters you may need to use a library directly.

My version "1.10" turned into 1.1. What happened?

The original JSON probably had the value as a number rather than a string. Numbers do not preserve trailing zeros after the decimal point, so 1.10 and 1.1 are indistinguishable once parsed. Fix this by quoting the value in the source JSON ("1.10") so it stays a string through the conversion.

Should I prefer block style or flow style YAML?

Block style for almost everything. It is the form humans expect when they open a YAML file. Flow style is fine for very small embedded snippets or when you have a tiny array that fits on one line and would look silly stretched vertically. Most converters and libraries default to block style, so you usually do not need to do anything special.

Can I convert a JSON array (not an object) to YAML?

Yes. YAML happily represents top-level arrays as a list of dash-prefixed items. The JSON [1, 2, 3] becomes a YAML file with three lines, each beginning with a dash. Both formats handle this without any special handling.

Do JSON null values become anything special in YAML?

Yes, they become the YAML null literal, which can appear as null, ~, or as an empty value depending on the writer. All three are equivalent on the read side. The most common output is just null, but watch out for libraries that emit ~ because it surprises people who have not seen it before.

Why is my converted YAML missing comments I expected?

JSON does not support comments, so any comments you might have wanted in the YAML output were never in the source data to begin with. Comments have to be added by hand after conversion. There is no automatic way to inject them based on field names or values.

Is it safe to convert sensitive JSON data online?

Only if the converter does the work in your browser rather than uploading to a server. Many free online tools route the data through a backend, where it could be logged or cached. Browser-based converters keep the data on your machine. StackConvert's converter runs entirely in JavaScript, so your data does not leave your device during conversion.

What about anchors and aliases? Will they appear in my output?

JSON has no concept of references between objects, so on a fresh conversion your YAML output will not contain anchors. However, some YAML libraries detect duplicate object references in the parsed data and emit anchors automatically as a size optimization. If that breaks downstream tools, look for a noRefs or useReferences option in your library and turn it off.

How do I convert a multi-megabyte JSON file?

Online converters that load the whole file into a browser textarea will struggle past 5 to 10 MB. For larger files, use a streaming approach with a CLI tool. yq handles arbitrarily large inputs because it reads from disk rather than into memory at once. For truly massive files, consider whether you really want a single YAML document or whether splitting into multiple smaller files makes more sense.