Kubernetes JSON to YAML converter
Convert a manifest to YAML and find out whether it is actually ready to commit. Missing apiVersion, leftover status blocks and managedFields are all flagged.
Conversion happens in this browser tab. Nothing is uploaded, logged, or stored.
Kubernetes® is a registered trademark of The Linux Foundation. This is an independent tool, not affiliated with or endorsed by The Linux Foundation or the Kubernetes project. See trademarks.
What this page checks that a plain converter does not
Any converter will turn manifest JSON into YAML. This one also reads the document as a Kubernetes object and tells you when it is syntactically fine but will not do what you want:
- Missing
apiVersionorkind.kubectl applyrejects an object without both, with an error that does not name the file helpfully when you are applying a directory. - Missing
metadata.name, unlessgenerateNameis set. - Server-populated fields. If the document carries
status,metadata.uid,resourceVersion,creationTimestamp,generation,selfLinkormanagedFields, it came from a live cluster and should be cleaned before it goes into a repository. See below. kind: List. A list of objects has to be split into separate YAML documents with---before it can be applied.
The status bar turns amber for these rather than red, because the conversion succeeded — the warning is about the manifest, not the syntax.
Why manifests arrive as JSON
Almost nobody writes Kubernetes JSON by hand. It shows up because something emitted it:
kubectl get deploy checkout-api -o json, when someone needs to capture what is actually running.- Terraform's
kubernetes_manifestresource and thekubernetesprovider, which speak JSON internally. - Pulumi, CDK8s, and other tools that generate manifests from code.
- API responses from the cluster itself, or from an admission controller log.
- Helm's
--dry-run -o jsonoutput when you are checking what a chart will render.
In every case the destination is the same: a .yaml file that a human
will review in a pull request. YAML is what the ecosystem's documentation, examples,
and tooling assume, and it is the only one of the two that can carry a comment
explaining why a replica count is what it is.
Cleaning a live object before committing it
Cleaning the manifest is the step people miss, and it is the reason a converted
manifest sometimes fails to apply to a fresh cluster. Anything you pull with -o json
contains fields the API server added, not fields you authored.
| Field | Why it must go |
|---|---|
status | Observed state. Meaningless in a manifest, and enormous. |
metadata.uid | Identifies that one object on that one cluster. |
metadata.resourceVersion | Optimistic-concurrency token. Applying it can fail with a conflict. |
metadata.creationTimestamp | Set by the server; often serialises as null, which some validators reject. |
metadata.generation | Server-maintained counter. |
metadata.managedFields | Server-side apply bookkeeping. Frequently longer than the manifest itself. |
metadata.selfLink | Removed from the API entirely in 1.21; harmless but dead. |
spec.clusterIP on a Service | Allocated by the cluster. A hard-coded IP will not apply elsewhere. |
| Default-injected fields | Things like terminationMessagePath and dnsPolicy that you never set. Harmless, but they add noise to every future diff. |
The quickest way to strip them is kubectl-neat:
kubectl get deploy checkout-api -o json | kubectl neat > deployment.json
Or with jq, if you would rather not add a plugin:
kubectl get deploy checkout-api -o json \
| jq 'del(.status,
.metadata.uid,
.metadata.resourceVersion,
.metadata.creationTimestamp,
.metadata.generation,
.metadata.managedFields,
.metadata.selfLink,
.metadata.annotations["kubectl.kubernetes.io/last-applied-configuration"])'
Paste the result above, and the warnings should clear.
Converting several objects at once
Asking for more than one object gives you a List, not a stream:
kubectl get deploy,svc -n payments -o json # -> { "kind": "List", "items": [...] }
Converted directly, that produces one YAML document with an items array
under it. It is valid YAML, and kubectl apply does accept a
List — but it is not what anyone wants in a repository, because the
objects cannot be reviewed, moved, or applied individually.
Split it first:
# one YAML document per object, separated by ---
kubectl get deploy,svc -n payments -o json \
| jq -c '.items[]' \
| while read -r o; do echo "---"; echo "$o" | yq -P; done > manifests.yaml
# or write one file per object
kubectl get deploy -o json | jq -c '.items[]' | while read -r o; do
name=$(echo "$o" | jq -r '.metadata.name')
echo "$o" | yq -P > "$name.yaml"
done
Where converted manifests go wrong
Environment variable values must be strings
Every value in an env entry has to be a string. JSON's
"2500" is already correct, and the converter keeps the quotes for exactly
this reason. Write value: 2500 by hand and the API server rejects the
object with a type error, because it wanted a string and got an integer.
Quantities that look like numbers
cpu: 500m and memory: 512Mi are fine unquoted, since
neither parses as a number. But a whole-CPU request written as cpu: 1 is
an integer, and while Kubernetes accepts it, mixing 1 and
"1" across files makes diffs noisy. Pick one and stay with it.
Version tags that lose a zero
An image tag inside a string is safe. A chart value like
version: 1.10 is not: unquoted, YAML reads it as the float 1.1 and your
deployment pulls the wrong thing. The
silent failures table lists the rest of this
family.
Tabs
If you hand-edit the converted output and your editor inserts a tab, the manifest
stops parsing entirely. YAML forbids tabs in indentation — see the
indentation rules. Set
indent_style = space for *.yaml in your
.editorconfig.
The output is valid YAML but invalid Kubernetes
This tool checks structure, not schema. It cannot know that
spec.replicas must be an integer or that your CRD requires a particular
field. Before committing, ask the cluster:
kubectl apply --dry-run=client -f deployment.yaml # schema, no cluster contact
kubectl apply --dry-run=server -f deployment.yaml # full validation, including admission
Doing it without a browser
# single object, straight from the cluster to a file
kubectl get deploy checkout-api -o yaml > deployment.yaml
# JSON you already have
yq -P -o=yaml deployment.json > deployment.yaml
# clean and convert in one pass
kubectl get deploy checkout-api -o json | kubectl neat | yq -P > deployment.yaml
kubectl get -o yaml is the obvious route when you have cluster access,
and it is the right one. This page is for the times you do not: a manifest pasted into
a ticket, output from a CI log, a chart rendered by someone else, or JSON from a
system that has no kubectl anywhere near it.
Manifests do not leave your browser
A manifest is a map of your infrastructure. Even with Secrets held elsewhere, it names your registry, your internal hostnames, your namespaces, your service accounts, and the exact image versions you are running — which is a list of the CVEs you are exposed to, for anyone who cares to look.
None of that is transmitted here. The conversion and the manifest checks both run in JavaScript inside this tab, on your machine. There is no upload step, no server that could log it, and nothing is kept when you close the page.