Skip to content

Data structure examples

Scalars

String

Input (a.json):

{"name":"alice","version":"1.0"}

Read a string field:

nesdit a.json --query '.name'

Stdout: "alice"

Set a string field:

nesdit a.json --query '.name = "bob"'

Stdout:

{"name":"bob","version":"1.0"}

Integer

Input:

{"count":0}

Set:

nesdit a.json --query '.count = 42'

Stdout: {"count":42}

Increment with |=:

nesdit a.json --query '.count |= . + 1'

Stdout: {"count":1}

Float

Input:

{"ratio":0.5}
nesdit a.json --query '.ratio = 1.25'

Stdout: {"ratio":1.25}

Boolean

Input:

{"enabled":false}
nesdit a.json --query '.enabled = true'

Stdout: {"enabled":true}

Null

Input:

{"key":"value"}

Set a field to null:

nesdit a.json --query '.key = null'

Stdout: {"key":null}

Warning

TOML cannot represent null. Setting a field to null in a TOML file is an error:

nesdit: error: config.toml: format.incompatible: TOML cannot represent null at .key


Nested objects

Input (config.json):

{"app":{"name":"myapp","settings":{"timeout":30,"retries":3}}}

Deep key access:

nesdit config.json --query '.app.settings.timeout'

Stdout: 30

Nested mutation:

nesdit config.json --query '.app.settings.timeout = 60'

Stdout:

{"app":{"name":"myapp","settings":{"timeout":60,"retries":3}}}

Partial update (preserves sibling keys):

nesdit config.json --query '.app.name = "newapp"'

Stdout:

{"app":{"name":"newapp","settings":{"timeout":30,"retries":3}}}

Arrays

Input (data.json):

{"items":[10,20,30,40,50]}

Index access:

nesdit data.json --query '.items[0]'

Stdout: 10

Update by index:

nesdit data.json --query '.items[2] = 99'

Stdout: {"items":[10,20,99,40,50]}

Map over all elements (.[]=|= ...):

nesdit data.json --query '.items[] |= . * 2'

Stdout: {"items":[20,40,60,80,100]}

Append an element:

nesdit data.json --create-missing --query '.items += [99]'

Stdout: {"items":[10,20,30,40,50,99]}

Delete by index:

nesdit data.json --query 'del(.items[1])'

Stdout: {"items":[10,30,40,50]}

Filter with select

select(predicate) keeps only elements for which the predicate is true. Wrap with array reconstruction to filter an array-of-maps:

Input (services.yaml):

services:
  - name: api
    enabled: true
  - name: worker
    enabled: false
  - name: scheduler
    enabled: true
nesdit --format yaml --query '.services = [.services[] | select(.enabled == true)]' services.yaml

Stdout:

services:
  - name: api
    enabled: true
  - name: scheduler
    enabled: true

Key order within each map entry is preserved. The worker entry is dropped because .enabled == false.


Array-of-maps

Input (pods.yaml):

pods:
  - name: web
    replicas: 1
    image: nginx
  - name: worker
    replicas: 2
    image: python
  - name: cache
    replicas: 1
    image: redis

Update the first element:

nesdit pods.yaml --query '.pods[0].replicas = 3'

Stdout:

pods:
  - name: web
    replicas: 3
    image: nginx
  - name: worker
    replicas: 2
    image: python
  - name: cache
    replicas: 1
    image: redis

Key order within each map entry is preserved.

Note

Positional reconciliation: When a jq expression reshapes an array (e.g., sort_by, reverse), each output element inherits key order from the element at the same positional index in the input. This is deterministic but may produce surprising key orderings if the array is reordered. This is a documented v1 behaviour (DR-007).


Mixed-depth structures

Input (mixed.json):

{"meta":{"tags":["a","b","c"],"counts":{"x":1,"y":2}}}

Access array inside nested object:

nesdit mixed.json --query '.meta.tags[1]'

Stdout: "b"

Mutate deep inside:

nesdit mixed.json --query '.meta.counts.x = 99'

Stdout:

{"meta":{"tags":["a","b","c"],"counts":{"x":99,"y":2}}}

YAML 1.1 vs 1.2 booleans

YAML 1.2 (the default) only recognises true and false as booleans. Values like yes, no, on, and off are plain strings.

Input (flags.yaml):

enabled: yes
disabled: no
switch_on: on
switch_off: off

Default (YAML 1.2 — yes is a string):

nesdit flags.yaml --query '.enabled'

Stdout: yes

With --yaml-version 1.1yes is decoded as boolean true:

nesdit --yaml-version 1.1 flags.yaml --query '.enabled'

Stdout: true

nesdit --yaml-version 1.1 flags.yaml --query '.disabled'

Stdout: false

nesdit --yaml-version 1.1 flags.yaml --query '.switch_on'

Stdout: true

Note

The encoder always writes YAML 1.2 output regardless of --yaml-version. Setting --yaml-version 1.1 only affects how the input is decoded.

Available in v1

The --yaml-version flag was included in v1 scope despite appearing in the RFC's deferral list. It is fully supported.


TOML-specific types

Integer vs float

TOML distinguishes integers from floats at the type level. nesdit preserves this distinction:

Input (nums.toml):

count = 42
ratio = 3.14

Update the integer:

nesdit nums.toml --query '.count = 100'

Stdout: count = 100\nratio = 3.14

Update to a float:

nesdit nums.toml --query '.ratio = 2.718'

Stdout: count = 42\nratio = 2.718

Inline tables

nesdit emits TOML nested objects as inline tables to preserve key order. Input with [section] syntax is read correctly:

Input (project.toml):

[package]
name = "mylib"
version = "0.1.0"
nesdit project.toml --query '.package.version = "0.2.0"'

Stdout:

package = {name = "mylib", version = "0.2.0"}

The [section] input was read; the output uses inline-table syntax. Round-trips are byte-stable: running the same command again on this output produces byte-identical output.