Skip to content

Converting Between JSON and YAML on the Command Line ​

fx reads YAML as input and can write YAML with the built-in YAML.stringify, so one tool handles both directions of the conversion. Install fx and follow the examples below.

Convert YAML to JSON ​

Pass --yaml and the . argument to print the document as pretty JSON:

bash
cat config.yaml | fx --yaml .

Input:

yaml
# service config
service:
  name: billing-api
  port: 8080
database:
  host: db.internal
features:
  - invoices
  - refunds

Output:

json
{
  "service": {
    "name": "billing-api",
    "port": 8080
  },
  "database": {
    "host": "db.internal"
  },
  "features": [
    "invoices",
    "refunds"
  ]
}

Files ending in .yaml or .yml are detected by extension, so fx config.yaml . works without the flag. With stdin you always need --yaml. Comments are dropped, since JSON has no comments. Save the result with fx config.yaml . > config.json.

Convert JSON to YAML ​

Pass YAML.stringify as an argument. It returns a string, and fx prints strings without quotes, so the output is plain YAML:

bash
fx users.json YAML.stringify

Input:

json
[
  {"id": 1, "name": "Alice", "role": "admin", "active": true},
  {"id": 2, "name": "Bob", "role": "viewer", "active": false}
]

Output:

yaml
- id: 1
  name: Alice
  role: admin
  active: true
- id: 2
  name: Bob
  role: viewer
  active: false

Strings that YAML would read as another type keep their quotes ("yes", "0755", "1.0"), and strings with newlines become |- block scalars, so converting to YAML and back to JSON gives you the same data. You can filter first: fx users.json '?.active' '@.name' YAML.stringify prints - Alice.

Convert docker-compose.yml or a Kubernetes Manifest to JSON ​

Compose files and manifests are ordinary YAML:

bash
fx docker-compose.yml .

Input:

yaml
services:
  web:
    image: nginx:1.27
    ports:
      - "8080:80"
  db:
    image: postgres:16

Output:

json
{
  "services": {
    "web": {
      "image": "nginx:1.27",
      "ports": [ "8080:80" ]
    },
    "db": {
      "image": "postgres:16"
    }
  }
}

You can query a manifest the same way you query JSON, for example to get the container image from a Deployment:

bash
fx deployment.yaml '.spec.template.spec.containers[0].image'
registry.example.com/billing-api:1.4.0

Edit a YAML Value and Write YAML Back ​

Change the parsed data with JavaScript, then run YAML.stringify as the last step. The expression x.field = value, x assigns the value and returns the whole document:

bash
fx config.yaml 'x.service.port = 9090, x' 'x.features.push("exports"), x' YAML.stringify > config.new.yaml

Contents of config.new.yaml (key order is kept, comments are lost, list items move to the parent key's indent):

yaml
service:
  name: billing-api
  port: 9090
database:
  host: db.internal
features:
- invoices
- refunds
- exports

WARNING

Do not redirect to the file you are reading (fx a.yaml ... > a.yaml). The shell empties the file before fx reads it. Write to a new file and move it into place afterwards.

Handle Multi-Document YAML (---) ​

fx splits a YAML stream on --- and handles each document as a separate value, the same way it handles newline-delimited JSON:

bash
cat multi.yaml | fx --yaml '.kind'

Input:

yaml
apiVersion: v1
kind: Service
metadata:
  name: billing
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: billing-config

Output:

Service
ConfigMap

To keep only one document, return skip for the others: 'x.kind == "ConfigMap" ? x : skip'.

Running YAML.stringify on each document separately does not put the --- separators back. To get valid multi-document YAML, collect the documents into an array with --slurp and join them yourself:

bash
cat multi.yaml | fx --yaml -s 'x => x.map(YAML.stringify).join("---\n")'
yaml
apiVersion: v1
kind: Service
metadata:
  name: billing
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: billing-config

Parse a YAML String Embedded in JSON ​

APIs sometimes return YAML as a string field, such as Helm values or CI configs. YAML.parse turns that string into an object:

bash
fx release.json 'x.values = YAML.parse(x.values), x'

Input:

json
{
  "release": "billing-api",
  "values": "replicas: 3\nimage:\n  tag: 1.4.0\n"
}

Output:

json
{
  "release": "billing-api",
  "values": {
    "replicas": 3,
    "image": {
      "tag": "1.4.0"
    }
  }
}

See Also ​