How to convert json to a kubernetes yaml manifest
- Step 1Export the live object as JSON — Run
kubectl get deployment my-app -n prod -o json > deployment.json, or fetch the resource from the Kubernetes API as JSON. For a whole namespace,kubectl get all -o jsongives aListobject you can split first. - Step 2Strip runtime fields you should not commit — The converter does not remove them, so do it first. Drop
status,metadata.managedFields,metadata.resourceVersion,metadata.uid,metadata.generation, andmetadata.creationTimestampusing json-key-filter. These are server-managed and will cause drift or apply warnings if committed. - Step 3Drop the cleaned JSON file on the tool — The converter takes a file, not pasted text — drop your
.jsonfile onto the dropzone. The free tier accepts files up to 2 MB; Pro raises this to 100 MB, which comfortably covers even large multi-container Deployments and CRDs. - Step 4Choose indent 2 and run — Leave indent at 2 for kubectl-compatible YAML. Click Convert to YAML. Avoid indent 4 here — it expands sequences onto separate lines, which is valid YAML but not the Kubernetes manifest style your reviewers expect.
- Step 5Spot-check null fields and quoted keys — Scan the output for
nullvalues on optional spec fields (the API often prefers them omitted) and for any key that got quoted (js-yaml quotes keys it reads as YAML 1.1 keywords). Remove or adjust as needed before saving. - Step 6Save and commit to your GitOps repo — Download the
.yaml(the tool names it after your input file), save it asmanifests/deployment.yaml, and commit. ArgoCD or Flux reconciles it against the cluster. To confirm a round-trip, you can convert the YAML back with yaml-to-json and diff against the original.
The two real conversion controls
These are the only options exposed in the json-to-yaml UI. Line width (80) and reference handling are fixed at sensible defaults and are not user-adjustable.
| Control | Values | Default | What it does for Kubernetes |
|---|---|---|---|
| Indent | 2 or 4 spaces | 2 | Use 2. Indent 2 gives the compact - name: app sequence style kubectl uses. Indent 4 puts the - on its own line with the item indented under it — valid YAML, but not manifest style |
| Sort keys alphabetically | on / off | off (preserves order) | Off keeps the API's field order (apiVersion, kind, metadata, spec). On sorts every mapping alphabetically — handy for byte-stable diffs between two exports, but reorders kind below metadata |
| Line width (fixed) | 80 columns | 80 (not adjustable) | Long single-line strings (e.g. a long command) fold across lines with >-. Rarely an issue for manifests, but be aware multi-line args may wrap |
| Anchors / aliases (fixed) | disabled | noRefs = true | Shared sub-objects are written out in full each time — no &anchor/*alias appears. Kubernetes does not support YAML anchors in manifests, so this is the correct default |
How JSON types map to Kubernetes YAML
js-yaml type mapping for the field shapes you hit most in Kubernetes objects.
| JSON in | YAML out | Kubernetes note |
|---|---|---|
"containerPort": 8080 | containerPort: 8080 | Unquoted integer — correct. The API rejects quoted ports |
"enabled": true | enabled: true | Unquoted boolean — correct for spec flags |
"optionalField": null | optionalField: null | Literal null. The API tolerates it for optional fields but often prefers the field omitted — review and remove |
"app.kubernetes.io/name": "web" | app.kubernetes.io/name: web | Dotted/slashed label key preserved unquoted |
"value": "123" | value: '123' | A string that looks numeric is quoted to stay a string — correct for env var values |
"status": { ... } | status: (full block) | Not stripped. Filter it out before converting |
Cookbook
Real kubectl exports converted to manifest YAML. Names and namespaces are illustrative; no cluster data is uploaded.
kubectl get -o json → committed Deployment manifest
ExampleThe end-to-end GitOps move: export the live Deployment, strip server fields, convert at indent 2, commit. The converter alone won't strip status — that's why json-key-filter is the prior step.
1. kubectl get deployment web -n prod -o json > web.json
2. json-key-filter → remove: status, metadata.managedFields,
metadata.resourceVersion, metadata.uid, metadata.creationTimestamp
3. json-to-yaml (indent 2) →
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: prod
spec:
replicas: 3
selector:
matchLabels:
app.kubernetes.io/name: web
template:
spec:
containers:
- name: web
image: nginx:1.25
ports:
- containerPort: 8080Indent 2 vs indent 4 on a container list
ExampleSame JSON, two indent settings. Indent 2 is the manifest style; indent 4 expands the sequence dash onto its own line. Both parse identically in Kubernetes, but reviewers and linters expect the compact form.
JSON: {"containers":[{"name":"app","image":"nginx"}]}
Indent 2 (use this):
containers:
- name: app
image: nginx
Indent 4 (avoid for manifests):
containers:
-
name: app
image: nginxInteger ports and booleans stay typed
ExampleA common worry is that conversion quotes everything. It doesn't — numbers and booleans stay unquoted, which is exactly what the Kubernetes schema requires.
JSON:
{"spec":{"replicas":3,"template":{"spec":{"hostNetwork":true,
"containers":[{"ports":[{"containerPort":443}]}]}}}}
YAML (indent 2):
spec:
replicas: 3
template:
spec:
hostNetwork: true
containers:
- ports:
- containerPort: 443Null on an optional field — review before committing
Examplekubectl frequently emits null for unset optional fields. YAML keeps them as null. The API accepts this, but a reviewer-friendly manifest omits them.
JSON (from kubectl):
{"spec":{"strategy":{"rollingUpdate":null},"replicas":2}}
YAML:
spec:
strategy:
rollingUpdate: null # <- review: usually drop this line
replicas: 2Sort keys on for a deterministic diff
ExampleWhen comparing two exports of the same object, enabling sort-keys makes both files byte-stable so the diff shows only real changes. The trade-off is that canonical field order (apiVersion → kind → metadata → spec) is lost.
JSON: {"kind":"Service","apiVersion":"v1","metadata":{"name":"web"}}
sortKeys ON →
apiVersion: v1
kind: Service
metadata:
name: web
(alphabetical: apiVersion before kind before metadata)Errors and edge cases
Real errors and silent failures sourced from each platform's own documentation. Match the wording to the row, fix what the row says to fix.
status / managedFields are kept, not stripped
By designThe converter dumps every key it receives. If you feed it raw kubectl get -o json, the output will contain status: and metadata.managedFields: — exactly the runtime cruft you should not commit. Remove those keys with json-key-filter before converting. This is intentional: silently dropping fields would be unsafe for a general JSON→YAML tool.
Indent 4 breaks manifest sequence style
ExpectedAt indent 4, js-yaml writes a sequence item as a bare - on one line with the mapping indented beneath it. It parses fine, but it does not match kubectl/manifest conventions and may trip strict style linters like yamllint with custom rules. Keep indent at 2 for Kubernetes.
Large integer IDs lose precision
Precision lossJSON numbers larger than 2^53 (about 9 quadrillion) exceed JavaScript's safe integer range. The browser's JSON.parse rounds them before YAML ever sees them, so a 20-digit generation or external ID can change. Kubernetes rarely uses numbers this large, but if a CRD field does, store it as a JSON string to preserve it.
Duplicate keys in the source JSON
Last winsIf the JSON contains the same key twice in one object, JSON.parse keeps only the last occurrence — the first is silently discarded before conversion. Malformed kubectl output won't do this, but hand-edited JSON might. Validate first with json-validator.
Invalid JSON input
ErrorThe converter calls JSON.parse on the file. A trailing comma, a comment, or an unquoted key throws a parse error and nothing converts. Kubernetes objects from kubectl are always strict JSON; if you hand-edited the file, fix it with json-format-fixer first.
Secret data is base64, not decrypted
PreservedA Secret object's data map holds base64-encoded values. The converter passes those base64 strings through verbatim — it does not decode or re-encode them. The YAML Secret remains functionally identical to the JSON one. Treat the output as sensitive and avoid committing real Secret values to Git.
List object with many items
Supportedkubectl get pods -o json returns a List with an items array. The converter handles it, producing one big YAML document with an items: sequence — not separate --- documents. The tool does not emit multi-document YAML, so to split a List into individual manifests, separate them in the JSON first.
Long command/args fold with >-
PreservedA single-line command or args value longer than 80 characters is wrapped using a folded block scalar (>-). The folded value reconstructs to the same string, so Kubernetes runs the identical command. If you prefer it on one line for readability, the meaning is unchanged regardless.
Quoted 'on'/'off'/'yes' style keys
PreservedKeys or string values that look like YAML 1.1 keywords (on, off, yes, no) are quoted on output to keep them as strings — correct behaviour. This is uncommon in Kubernetes objects but can appear in custom annotation values.
Frequently asked questions
Does this tool remove status and managedFields automatically?
No. The converter dumps every key it receives, so raw kubectl get -o json output produces YAML that still contains status:, metadata.managedFields:, resourceVersion, uid, and creationTimestamp. Strip those with json-key-filter before converting — they are server-managed runtime fields that cause drift if committed to a GitOps repo.
Which indent setting should I use for Kubernetes manifests?
Indent 2. It produces the compact - name: app sequence style that matches kubectl apply conventions and hand-written manifests. Indent 4 is valid YAML but writes the sequence dash on its own line, which no Kubernetes style guide uses and which some yamllint configs flag.
Will JSON null values cause problems in the YAML?
JSON null becomes the literal YAML null. Kubernetes tolerates null for optional fields, but for many fields the API prefers the key to be omitted entirely. Review null-valued lines in the output and delete any the API would reject or that you'd rather leave unset.
How are integer ports and replica counts handled?
They stay unquoted integers — containerPort: 8080, replicas: 3, port: 443. That is exactly what the Kubernetes schema requires; quoted ports are rejected. Booleans (true/false) are likewise preserved as unquoted YAML booleans.
Are dotted label keys like app.kubernetes.io/name preserved?
Yes. Keys containing dots and slashes are kept verbatim and unquoted: app.kubernetes.io/name: web. The converter does not split or escape them.
Is cluster JSON, including Secret data, sent to JAD Apps?
No. Conversion runs entirely in your browser using js-yaml. Live object JSON — including base64 Secret data and internal config — never reaches a JAD Apps server. The only server-side record when signed in is an anonymous run counter, no content.
Can it convert a whole namespace export at once?
Yes, but the result is one YAML document with an items: sequence (the shape of a kubectl get all -o json List), not separate ----delimited manifests. The tool does not emit multi-document YAML. To get individual files, split the JSON into single objects before converting.
What's the file size limit?
The free tier caps input at 2 MB, which covers virtually any single Deployment, StatefulSet, or CRD. Pro raises the limit to 100 MB for large List exports. The tool takes a file, not pasted text.
Does it add YAML anchors for repeated blocks?
No. Anchor/alias generation is disabled (noRefs is fixed on), so repeated sub-objects are written out in full each time. Kubernetes manifests do not support anchors, so this is the safe default.
Can I round-trip back to JSON to verify nothing changed?
Yes. Convert the YAML back with yaml-to-json and compare against the original using json-diff. A clean diff (ignoring key order if you used sort-keys) confirms a faithful round-trip.
Why did a long command get wrapped across multiple lines?
Lines longer than 80 columns fold using a >- folded block scalar. The folded form reconstructs to the identical string, so the container runs the same command. The line width is fixed at 80 and is not user-adjustable.
How do I strip null fields after converting?
Strip them in JSON before converting — run the JSON through json-null-stripper to remove null-valued keys, then convert the cleaned JSON to YAML. The result has no null lines to review.
Privacy first
Conversion runs locally in your browser. No file is uploaded — only metadata counters are saved for signed-in dashboard stats.