# Introduction

{% hint style="warning" %}
You are viewing dasel v1 documentation.
{% endhint %}

Dasel (short for data-selector) allows you to query and modify data structures using selector strings.

## One tool to rule them all

Say good bye to learning new tools just to work with a different data format.

Dasel uses a standard selector syntax no matter the data format. This means that once you learn how to use dasel you immediately have the ability to query/modify any of the supported data types without any additional tools or effort.


# Installation

## Homebrew

The easiest way to get your hands on the latest version of dasel is to use homebrew:

```shell
brew install dasel
```

## Docker

Run dasel in docker using the image `ghcr.io/tomwright/dasel`.

### Usage

Run the docker image, passing in a dasel command with the executable excluded.

```shell
$ echo '{"name": "Tom"}' | docker run -i --rm ghcr.io/tomwright/dasel:latest -r json '.name'
"Tom"
```

### Versioning

New image versions are built and pushed automatically as part of the CI/CD pipeline in Github actions.

| Tag           | Description                                  |
| ------------- | -------------------------------------------- |
| `latest`      | The latest release version.                  |
| `development` | The latest build from `master` branch.       |
| `v*.*.*`      | The specified dasel release. E.g. `v1.13.6`. |

## ASDF

Using [asdf-vm](https://asdf-vm.com) and the [asdf-dasel plugin](https://github.com/asdf-community/asdf-dasel?ts=4).

```shell
asdf plugin add dasel https://github.com/asdf-community/asdf-dasel.git
asdf list all dasel
asdf install dasel <version>
asdf global dasel <version>
```

## Nix

To install using the [Nix Package Manager](https://nixos.org) (for non-NixOS)

```shell
nix-env -iA nixpkgs.dasel
```

Or NixOS:

```shell
nix-env -iA nixos.dasel
```

## Manual

You can download a compiled executable from the [latest release](https://github.com/TomWright/dasel/releases/latest).

{% hint style="info" %}
Don't forget to put the binary somewhere in your `PATH`.
{% endhint %}

{% tabs %}
{% tab title="Linux (64 bit)" %}

```
curl -sSLf "$(curl -sSLf https://api.github.com/repos/tomwright/dasel/releases/latest | grep browser_download_url | grep linux_amd64 | grep -v .gz | cut -d\" -f 4)" -L -o dasel && chmod +x dasel
mv ./dasel /usr/local/bin/dasel
```

{% endtab %}

{% tab title="Mac OS (64 bit)" %}

```
curl -sSLf "$(curl -sSLf https://api.github.com/repos/tomwright/dasel/releases/latest | grep browser_download_url | grep -v .gz | grep darwin_amd64 | cut -d\" -f 4)" -L -o dasel && chmod +x dasel
mv ./dasel /usr/local/bin/dasel
```

{% endtab %}

{% tab title="Windows" %}
Manually download a compiled executable from the [latest release](https://github.com/TomWright/dasel/releases/latest).
{% endtab %}
{% endtabs %}

## Scoop

Use the scoop command-line installer to install dasel on windows 10.

```shell
scoop bucket add extras
scoop install dasel
```

## Development Version

You can `go install` the `cmd/dasel` package to build and install dasel for you.

{% hint style="info" %}
You may need to prefix the command with `GO111MODULE=on` in order for this to work.
{% endhint %}

```
go install github.com/tomwright/dasel/cmd/dasel@master
```


# Update

{% hint style="warning" %}
This is a dasel feature and will cause the current executable to be replaced. This may cause side effects when used in conjunction with a package manager, and as such may not be included in some versions of dasel installed using package managers.
{% endhint %}

Dasel can self-update using the latest release on Github.

```shell
dasel update
```

If you have a development version of dasel this will fail with a warning.

To override this warning and update the development version to the latest release you can use:

```shell
dasel update --dev
```

This command can be disabled by building dasel with the `noupdater` build tag.


# Use as a go package

Dasel can be imported and used just like any other go package. This can be very useful if you need to manipulate data from your own applications.

## Import

As with any other go package, just use `go get`.

```shell
go get github.com/tomwright/dasel
```

## Usage

Once imported you do something like the following:

```go
package main
import (
    "encoding/json"
    "fmt"
    "github.com/tomwright/dasel"
)

func main() {
    var data interface{}
    _ = json.Unmarshal([]byte(`[{"name": "Tom"}, {"name": "Jim"}]`), &data)

    rootNode := dasel.New(data)

    result, _ := rootNode.Query(".[0].name")
    printNodeValue(result) // Tom

    results, _ := rootNode.QueryMultiple(".[*].name")
    printNodeValue(results...) // Tom\nJim

    _ = rootNode.Put(".[0].name", "Frank")
    printNodeValue(rootNode) // [map[name:Frank] map[name:Jim]]

    _ = rootNode.PutMultiple(".[*].name", "Joe")
    printNodeValue(rootNode) // [map[name:Joe] map[name:Joe]]

    outputBytes, _ := json.Marshal(rootNode.InterfaceValue())
    fmt.Println(string(outputBytes)) // [{"name":"Joe"},{"name":"Joe"}]
}

func printNodeValue(nodes ...*dasel.Node) {
    for _, n := range nodes {
        fmt.Println(n.InterfaceValue())
    }
}
```

From then on the rest of the docs and comments should be enough to get you going.

Just know that when using the command-line tool the `-m`,`--multiple` flag tells dasel to use `QueryMultiple`/`PutMultiple` instead of `Query`/`Put`.

If the information provided here isn't good enough please raise an issue/discussion.


# Select

## Description

This command allows you to select data from data structures.

It will not modify the source data in any way.

## Usage

```shell
dasel select -f <file> <selector>
```

### Flags

| Flag                             | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `-f`, `--file`                   | <p>Specify the file to query. This is required unless you are piping in data.</p><p>If piping in data you can optionally pass <code>-f stdin</code>/<code>-f -</code>.</p>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `-r`, `--read`                   | <p>Specify the parser to use when reading the input data.</p><p>This is required if you are piping in data, otherwise dasel will use the given file extension to guess which parser to use.</p><p>See <a href="/pages/-MXgNylC4AkvSj351jU3">supported file types</a>.</p>                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `-w`, `--write`                  | <p>Specify the parser to use when writing the output data.</p><p>If not provided dasel will attempt to use the<code>--read</code> flag to determine which parser to use.</p><p>See <a href="/pages/-MXgNylC4AkvSj351jU3">supported file types</a>.</p>                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `-p`, `--parser`                 | Shorthand for `-r <value> -w <value>`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `-m`, `--multiple`               | <p>Tells dasel to select multiple items.</p><p>See <a href="/pages/-MXgNylAqqL66l3g7A2u">multiple</a>.</p>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `-s`, `--selector`, `<selector>` | <p>Specify the selector to use. See <a href="/pages/-MXgNylFbABKYJMirPOA">selectors</a> for more information.</p><p>If no selector flag is given, dasel assumes the first argument given is the selector.</p><p>This is required.</p>                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `--plain`                        | <p>By default, dasel formats the output using the specified parser.</p><p>If this flag is used no formatting occurs and the results output as a string.</p>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `-n`, `--null`                   | <p>Output <code>null</code> instead of <code>ValueNotFound</code> errors.</p><p>See <a href="/pages/-MXgNylB12PQNes7fnNt">null</a>.</p>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `-c`, `--compact`                | This tells dasel to output compact data where possible. E.g. not pretty printing JSON.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `--length`                       | <p>This tells dasel to output the length of the value found.</p><ul><li><code>\[1, 2, 3]</code> - <code>3</code>: The number of elements within the array.</li><li><code>{"a": 1, "b": 2}</code> - <code>2</code>: The number of elements within the map.</li><li><code>"Hello there"</code> - <code>11</code>: The number of characters in the string.</li><li><p>Any other values are converted to strings and then treated as such:</p><ul><li><code>12345</code> - <code>5</code>: Numbers are converted to strings.</li><li><code>123.45</code> - <code>6</code>: Floats/decimals are converted to strings.</li><li><code>true</code> - <code>4</code>: Bools are converted to strings.</li></ul></li></ul> |
| `--merge-input-documents`        | See [merge input documents](/v1/usage/flags/merge-input-documents).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `--format`                       | See [format](/v1/usage/flags/format).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `--colour`                       | Colourise output.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `--color`                        | Alias of `--colour.`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `--escape-html`                  | See [escape html](/v1/usage/flags/escape-html).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |

## Example

### **Select the image within a kubernetes deployment manifest file:**

```
$ dasel select -f deployment.yaml "spec.template.spec.containers.(name=auth).image"
"tomwright/auth:v1.0.0"
```

### **Piping data into the select:**

```
$ cat deployment.yaml | dasel select -p yaml "spec.template.spec.containers.(name=auth).image"
"tomwright/auth:v1.0.0"
```


# Put

## Description

This command allows you to modify data at a given selector.

Dasel will create any data items that do not already exist allowing you to create entire data structures from nothing.

## Usage

```shell
dasel put <type> -f <file> <selector> <value>
```

{% hint style="warning" %}
If `--file` is used without `--out` then the source file will be updated.
{% endhint %}

| Flag                                                                     | Description                                                                                                                                                                                                                                                                             |
| ------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `<type>`                                                                 | <p>The type of value you want to put.</p><p>Available arguments:</p><ul><li>string</li><li>int</li><li>bool</li><li><a href="/pages/-MXgNyl7ffGG2BSMMQ-V">object</a></li><li><a href="/pages/-MXgNyl8K87ymt2xTTtt">document</a></li></ul>                                               |
| <p><code>\<value></code></p><p><code>-v</code>, <code>--value</code></p> | <p>The value to write.</p><p>Dasel will parse this value as a string, int, or bool from this value depending on the given <code>type</code>.</p><p>If no <code>-v</code>, <code>--value</code> flag is given, the value is assumed to be the last argument.</p><p>This is required.</p> |
| <p><code>--value-file</code><br>Since <code>v1.27.0</code></p>           | <p>A path to a file containing the value.<br>If present, the contents of the file takes precedence over <code>-v, --value</code>.</p>                                                                                                                                                   |
| `-f`, `--file`                                                           | <p>Specify the file to query. This is required unless you are piping in data.</p><p>If piping in data you can optionally pass <code>-f stdin</code>/<code>-f -</code>.</p>                                                                                                              |
| `-o`, `--out`                                                            | <p>Specify the output file. If present, results will be written to the given file. If not present, results will be written to the input file (or stdout if none given).</p><p>To force output to be written to stdout, pass <code>-o stdout</code>or<code>-o -</code>.</p>              |
| `-r`, `--read`                                                           | <p>Specify the parser to use when reading the input data.</p><p>This is required if you are piping in data, otherwise dasel will use the given file extension to guess which parser to use.</p><p>See <a href="/pages/-MXgNylC4AkvSj351jU3">supported file types</a>.</p>               |
| `-w`, `--write`                                                          | <p>Specify the parser to use when writing the output data.</p><p>If not provided dasel will attempt to use the <code>--out</code> and <code>--read</code> flags to determine which parser to use.</p><p>See <a href="/pages/-MXgNylC4AkvSj351jU3">supported file types</a>.</p>         |
| `-p`, `--parser`                                                         | Shorthand for `-r <value> -w <value>`                                                                                                                                                                                                                                                   |
| `-m`, `--multiple`                                                       | <p>Tells dasel to put multiple items.</p><p>See <a href="/pages/-MXgNylAqqL66l3g7A2u">multiple</a>.</p>                                                                                                                                                                                 |
| `-s`, `--selector`, `<selector>`                                         | <p>Specify the selector to use. See <a href="/pages/-MXgNylFbABKYJMirPOA">selectors</a> for more information.</p><p>If no selector flag is given, dasel assumes the first argument given is the selector.</p><p>This is required.</p>                                                   |
| `--plain`                                                                | <p>By default, dasel formats the output using the specified parser.</p><p>If this flag is used no formatting occurs and the results output as a string.</p>                                                                                                                             |
| `-c`, `--compact`                                                        | This tells dasel to output compact data where possible. E.g. not pretty printing JSON.                                                                                                                                                                                                  |
| `--merge-input-documents`                                                | See [merge input documents](/v1/usage/flags/merge-input-documents).                                                                                                                                                                                                                     |
| `--escape-html`                                                          | See [escape html](/v1/usage/flags/escape-html).                                                                                                                                                                                                                                         |

## Example

### Put string

```shell
$ echo "name: Tom" | ./dasel put string -p yaml ".name" Jim
name: Jim
```

### Create documents from scratch

You can pipe multiple dasel commands together in order to build entire documents or make multiple changes:

```shell
$ echo '' |
dasel put string -p yaml '.servers.[].bind_dn' 'x' |
dasel put string -p yaml -m '.servers.[*].attributes.name' 'y' |
dasel put string -p yaml -m '.servers.[*].group_mappings.[].group_dn' 'a' |
dasel put string -p yaml -m '.servers.[*].group_mappings.[].group_dn' 'b'
servers:
  - attributes:
      name: "y"
    bind_dn: x
    group_mappings:
      - group_dn: a
      - group_dn: b
```


# Put object

## Description

This command allows you to modify data at a given selector.

It generally works in the same way as [put](/v1/usage/put), but allows you to write entire maps with a single command.

Note that `put object` will completely overwrite any existing data at the given selector.

## Usage

```shell
dasel put object -f <file> -t <type> -t <type> <selector> <value:key=value> <value:key=value>
```

{% hint style="info" %}
Omit the types and values to create an empty object/map.
{% endhint %}

| Flag                             | Description                                                                                                                                                                                                                                                                     |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `-t`, `<type>`                   | <p>The type of value you want to put.</p><p>You must repeat this argument for each value provided.</p><p>Available arguments:</p><ul><li>string</li><li>int</li><li>bool</li></ul>                                                                                              |
| `<value>`                        | <p>The key + value to write as<code>key=value</code></p><p>Dasel will parse this value as a string, int, or bool depending on the given <code>type</code>.</p><p>This is required.</p>                                                                                          |
| `-f`, `--file`                   | <p>Specify the file to query. This is required unless you are piping in data.</p><p>If piping in data you can optionally pass <code>-f stdin</code>/<code>-f -</code>.</p>                                                                                                      |
| `-o`, `--out`                    | <p>Specify the output file. If present, results will be written to the given file. If not present, results will be written to the input file (or stdout if none given).</p><p>To force output to be written to stdout, pass <code>-o stdout</code>or<code>-o -</code>.</p>      |
| `-r`, `--read`                   | <p>Specify the parser to use when reading the input data.</p><p>This is required if you are piping in data, otherwise dasel will use the given file extension to guess which parser to use.</p><p>See <a href="/pages/-MXgNylC4AkvSj351jU3">supported file types</a>.</p>       |
| `-w`, `--write`                  | <p>Specify the parser to use when writing the output data.</p><p>If not provided dasel will attempt to use the <code>--out</code> and <code>--read</code> flags to determine which parser to use.</p><p>See <a href="/pages/-MXgNylC4AkvSj351jU3">supported file types</a>.</p> |
| `-p`, `--parser`                 | Shorthand for `-r <value> -w <value>`                                                                                                                                                                                                                                           |
| `-m`, `--multiple`               | <p>Tells dasel to put multiple items.</p><p>See <a href="/pages/-MXgNylAqqL66l3g7A2u">multiple</a>.</p>                                                                                                                                                                         |
| `-s`, `--selector`, `<selector>` | <p>Specify the selector to use. See <a href="/pages/-MXgNylFbABKYJMirPOA">selectors</a> for more information.</p><p>If no selector flag is given, dasel assumes the first argument given is the selector.</p><p>This is required.</p>                                           |
| `--plain`                        | <p>By default, dasel formats the output using the specified parser.</p><p>If this flag is used no formatting occurs and the results output as a string.</p>                                                                                                                     |
| `-c`, `--compact`                | This tells dasel to output compact data where possible. E.g. not pretty printing JSON.                                                                                                                                                                                          |
| `--merge-input-documents`        | See [merge input documents](/v1/usage/flags/merge-input-documents).                                                                                                                                                                                                             |
| `--escape-html`                  | See [escape html](/v1/usage/flags/escape-html).                                                                                                                                                                                                                                 |

## Example

### Put object

```shell
$ echo "" | dasel put object -p yaml -t string -t int "my.favourites" colour=red number=3
my:
  favourites:
    colour: red
    number: 3
```


# Put document

## Description

This command allows you to modify data at a given selector.

It generally works in the same way as [put](/v1/usage/put), but allows you to write entire documents with a single command.

Note that `put document` will completely overwrite any existing data at the given selector.

## Usage

```shell
dasel put document -f <file> -d <document-parser> <selector> <document>
```

| Flag                                                           | Description                                                                                                                                                                                                                                                                     |
| -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `<document>`                                                   | <p>The document you want to put, as a marshaled/encoded string.</p><p>This is required.</p>                                                                                                                                                                                     |
| <p><code>--value-file</code><br>Since <code>v1.27.0</code></p> | <p>A path to a file containing the document.<br>If present, the contents of the file takes precedence over <code>\<document></code>.</p>                                                                                                                                        |
| `-d`, `<document-parser>`                                      | <p>Specify the parser to use when reading the document value.</p><p>If no value is provided, the read parser is used.</p><p>See <a href="/pages/-MXgNylC4AkvSj351jU3">supported file types</a>.</p>                                                                             |
| `-f`, `--file`                                                 | <p>Specify the file to query. This is required unless you are piping in data.</p><p>If piping in data you can optionally pass <code>-f stdin</code>/<code>-f -</code>.</p>                                                                                                      |
| `-o`, `--out`                                                  | <p>Specify the output file. If present, results will be written to the given file. If not present, results will be written to the input file (or stdout if none given).</p><p>To force output to be written to stdout, pass <code>-o stdout</code>or<code>-o -</code>.</p>      |
| `-r`, `--read`                                                 | <p>Specify the parser to use when reading the input data.</p><p>This is required if you are piping in data, otherwise dasel will use the given file extension to guess which parser to use.</p><p>See <a href="/pages/-MXgNylC4AkvSj351jU3">supported file types</a>.</p>       |
| `-w`, `--write`                                                | <p>Specify the parser to use when writing the output data.</p><p>If not provided dasel will attempt to use the <code>--out</code> and <code>--read</code> flags to determine which parser to use.</p><p>See <a href="/pages/-MXgNylC4AkvSj351jU3">supported file types</a>.</p> |
| `-p`, `--parser`                                               | Shorthand for `-r <value> -w <value>`                                                                                                                                                                                                                                           |
| `-m`, `--multiple`                                             | <p>Tells dasel to put multiple items.</p><p>See <a href="/pages/-MXgNylAqqL66l3g7A2u">multiple</a>.</p>                                                                                                                                                                         |
| `-s`, `--selector`, `<selector>`                               | <p>Specify the selector to use. See <a href="/pages/-MXgNylFbABKYJMirPOA">selectors</a> for more information.</p><p>If no selector flag is given, dasel assumes the first argument given is the selector.</p><p>This is required.</p>                                           |
| `-c`, `--compact`                                              | This tells dasel to output compact data where possible. E.g. not pretty printing JSON.                                                                                                                                                                                          |
| `--merge-input-documents`                                      | See [merge input documents](/v1/usage/flags/merge-input-documents).                                                                                                                                                                                                             |
| `--escape-html`                                                | See [escape html](/v1/usage/flags/escape-html).                                                                                                                                                                                                                                 |

## Example

### Put YAML document into JSON

```shell
$ echo '{"people":[]}' | dasel put document -p json -d yaml '.people.[]' 'name: Tom
colours:
- red
- green
- blue'
```

```json
{
  "people": [
    {
      "colours": ["red", "green", "blue"],
      "name": "Tom"
    }
  ]
}
```


# Delete

## Description

This command allows you to delete data at a given selector.

If the root node is deleted, an empty node of the same type will be output.

Note that if your root node is anything other than an object or array, dasel will output an empty object.

{% hint style="info" %}
Available since `v1.16.0.`
{% endhint %}

## Usage

```shell
dasel delete -f <file> <selector>
```

{% hint style="warning" %}
If `--file` is used without `--out` then the source file will be updated.
{% endhint %}

| Flag                             | Description                                                                                                                                                                                                                                                                     |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `-f`, `--file`                   | <p>Specify the file to query. This is required unless you are piping in data.</p><p>If piping in data you can optionally pass <code>-f stdin</code>/<code>-f -</code>.</p>                                                                                                      |
| `-o`, `--out`                    | <p>Specify the output file. If present, results will be written to the given file. If not present, results will be written to the input file (or stdout if none given).</p><p>To force output to be written to stdout, pass <code>-o stdout</code>or<code>-o -</code>.</p>      |
| `-r`, `--read`                   | <p>Specify the parser to use when reading the input data.</p><p>This is required if you are piping in data, otherwise dasel will use the given file extension to guess which parser to use.</p><p>See <a href="/pages/-MXgNylC4AkvSj351jU3">supported file types</a>.</p>       |
| `-w`, `--write`                  | <p>Specify the parser to use when writing the output data.</p><p>If not provided dasel will attempt to use the <code>--out</code> and <code>--read</code> flags to determine which parser to use.</p><p>See <a href="/pages/-MXgNylC4AkvSj351jU3">supported file types</a>.</p> |
| `-p`, `--parser`                 | Shorthand for `-r <value> -w <value>`                                                                                                                                                                                                                                           |
| `-m`, `--multiple`               | <p>Tells dasel to delete multiple items.</p><p>See <a href="/pages/-MXgNylAqqL66l3g7A2u">multiple</a>.</p>                                                                                                                                                                      |
| `-s`, `--selector`, `<selector>` | <p>Specify the selector to use. See <a href="/pages/-MXgNylFbABKYJMirPOA">selectors</a> for more information.</p><p>If no selector flag is given, dasel assumes the first argument given is the selector.</p><p>This is required.</p>                                           |
| `--plain`                        | <p>By default, dasel formats the output using the specified parser.</p><p>If this flag is used no formatting occurs and the results output as a string.</p>                                                                                                                     |
| `-c`, `--compact`                | This tells dasel to output compact data where possible. E.g. not pretty printing JSON.                                                                                                                                                                                          |
| `--merge-input-documents`        | See [merge input documents](/v1/usage/flags/merge-input-documents).                                                                                                                                                                                                             |
| `--escape-html`                  | See [escape html](/v1/usage/flags/escape-html).                                                                                                                                                                                                                                 |

## Example

### Delete property

```shell
$ echo '{
  "name": "Tom",
  "email": "contact@tomwright.me"
}' | dasel delete -p json '.email'
{
  "name": "Tom"
}
```


# Validate

## Description

This command allows you validate files.

It will not modify the source data in any way.

{% hint style="info" %}
Available since `v1.25.0.`
{% endhint %}

## Usage

```shell
dasel validate a.json b.yaml files/*.json
```

### Flags

| `--include-error` | <p>Tells dasel to output to include/exclude the error when a file fails validation.<br><br>Default to <code>true</code>.</p> |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------- |

## Example

### Validate an entire directory

```shell
$ dasel validate tests/assets/*
fail tests/assets/broken.json could not load input: could not unmarshal data: invalid character '}' after array element
fail tests/assets/broken.xml could not load input: could not unmarshal data: xml.Decoder.Token() - XML syntax error on line 1: element <a> closed by </b>
pass tests/assets/deployment.yaml
pass tests/assets/example.json
pass tests/assets/example.xml
pass tests/assets/example.yaml
Error: 2 files failed validation
```

### Validate a subset of files

```shell
$ dasel validate tests/assets/example.*
pass tests/assets/example.json
pass tests/assets/example.xml
pass tests/assets/example.yaml
```

### Validate specific files

```shell
$ dasel validate tests/assets/example.json tests/assets/example.yaml
pass tests/assets/example.json
pass tests/assets/example.yaml
```

## Pre-Commit

Add `dasel` hooks to `.pre-commit-config.yaml` file

```yaml
- repo: https://github.com/TomWright/dasel
  rev: v1.25.1
  hooks:
    - id: dasel-validate
```

for a native execution of dasel, or use:

* `dasel-validate-docker` pre-commit hook for executing dasel using the official [Docker images](https://daseldocs.tomwright.me/installation#docker)
* `dasel-validate-bin` pre-commit hook for executing dasel using the official [binary](https://github.com/TomWright/dasel-docs/blob/master/usage/installation/README.md)


# Flags

Some flags are used across commands or require a more in-depth explanation.


# Escape HTML

## Description

Tells dasel whether or not to escape HTML tags when writing data.

## Usage

Pass the `--escape-html=true` or `--escape-html=false` flag to any dasel command.

Defaults to `false`.

{% hint style="info" %}
Supported in JSON write parser since v1.21.0.
{% endhint %}

## Example

### True

```shell
$ echo '{"user": "tom <asd>"}' | dasel -r json --escape-html=true .
{
  "user": "tom \u003casd\u003e"
}
```

### False

```shell
$ echo '{"user": "tom <asd>"}' | dasel -r json --escape-html=false .
{
  "user": "tom <asd>"
}
```


# Format

## Description

Allows you to format dasel output according to the given template.

## Usage

Pass the `--format` flag to [select](/v1/usage/select) commands.

{% hint style="info" %}
Available in `select` commands since `v1.18.0`.
{% endhint %}

## Functions and accessors

The root context `.` is equal to the node found at the given selector.

It is recommended that you use the `select` function with a selector to access values, but you can access properties in the path with `.field.subField` if preferred.

| Function                    | Description                                                                                |
| --------------------------- | ------------------------------------------------------------------------------------------ |
| `select "selector"`         | Returns the node at the given selector.                                                    |
| `selectMultiple "selector"` | Returns a list of nodes found for the given selector.                                      |
| `query`                     | Alias of `select`.                                                                         |
| `queryMultiple`             | Alias of `selectMultiple`.                                                                 |
| `isFirst`                   | Returns `true` if the node being formatted is the first in a list of selected nodes.       |
| `isLast`                    | Returns `true` if the node being formatted is the last in a list of selected nodes.        |
| `format "template"`         | Allows recursive calls to the formatting capability. Useful when using a `selectMultiple`. |
| `newline`                   | Returns a newline character.                                                               |

{% hint style="info" %}
Dasel also provides access to [sprig](http://masterminds.github.io/sprig/) functions within templates to allow more functionality.
{% endhint %}

The templates are parsed using golang's `text/template` package so dasel also supports an array of conditional and loop statements by default.

| Description                 | Example                                                                                                                      |
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| If condition                | `{{ if x }} x is true {{ else }} x is false {{ end }}`                                                                       |
| If not condition            | `{{ if not x }} x is` false `{{ else }} x is true {{ end }}`                                                                 |
| Range                       | <p><code>Numbers:</code></p><p><code>{{ range .numbers -}}</code><br><code>- {{ . }}</code></p><p><code>{{ end }}</code></p> |
| Text and space manipulation | <https://pkg.go.dev/text/template#hdr-Text_and_spaces>                                                                       |

For more information refer to the [related documentation](https://pkg.go.dev/text/template#hdr-Functions).

## Example

### Select

```shell
$ echo '[
  {"name": "Tom", "email": "contact@tomwright.me"},
  {"name": "Jim", "email": "jim@gmail.com"}
]' | dasel -p json -m \
  --format '{{ select ".name" }},{{ select ".email" }}' \
  '.[*]'
Tom,contact@tomwright.me
Jim,jim@gmail.com
```

### SelectMultiple

```shell
$ echo '[
  {"name": "Tom", "emails": [
    {"email": "contact@tomwright.me", "primary": true},
    {"email": "tom@gmail.com", "primary": false}
  ]},
  {"name": "Jim", "emails": [
    {"email": "old@gmail.com", "primary": false},
    {"email": "jim@gmail.com", "primary": true}
  ]}
]' | dasel -p json -m \
  --format '{{ select ".name" }}:{{ newline }}{{ selectMultiple ".emails.[*]" | format "- {{ select \".email\" }}, {{ select \".primary\" }}{{ if not isLast }}{{ newline }}{{ end }}" }}' \
  '.[*]'
Tom:
- contact@tomwright.me, true
- tom@gmail.com, false
Jim:
- old@gmail.com, false
- jim@gmail.com, true
```


# Multiple

## Description

Tells dasel to select or put multiple items.

This causes the [dynamic](/v1/selectors/dynamic) selector to return all matching results rather than the first, and enables the [all indexes](/v1/selectors/all-indexes) selector.

All matches will be output on a new line.

## Usage

Pass the `-m`, `--multiple` flag to [select](/v1/usage/select) or [put](/v1/usage/put) commands.

## Example

### Select

```shell
$ echo '[{"name": "Tom"}, {"name": "Jim"}]' | dasel -p json -m '.[*].name'
"Tom"
"Jim"
```

### Put

```shell
$ echo '[{"name": "Tom"}, {"name": "Jim"}]' | dasel put string -p json -m '.[*].name' Frank
[
  {
    "name": "Frank"
  },
  {
    "name": "Frank"
  }
]
```


# Null

## Description

This flag tells dasel to output `null` instead of `ValueNotFound` errors.

## Usage

Pass the `-n`, `--null` flag to [select](/v1/usage/select) commands.

## Example

With the flag:

```
$ echo '[1]' | dasel -p json -n '.[1]'
null
```

Without the flag:

```shell
$ echo '[1]' | dasel -p json '.[1]'
Error: could not query node: could not find value: no value found for selector: .[1]: [1]
```


# Merge Input Documents

## Description

This flag tells dasel to merge input documents into an array.

Note that when `--merge-input-documents` is passed, even a single document will be converted to an array.

## Usage

Pass the `--merge-input-documents` to [select](/v1/usage/select) or [put](/v1/usage/put) commands.

## Example

With the flag:

```shell
$ echo 'foo: bar
---
baz: biz' | dasel -r yaml -w json --merge-input-documents .
[
  {
    "foo": "bar"
  },
  {
    "baz": "biz"
  }
]
```

Without the flag:

```shell
$ echo 'foo: bar
---
baz: biz' | dasel -r yaml -w json .
{
  "foo": "bar"
}
{
  "baz": "biz"
}
```

## Notes

Take note that merge in this context means taking all of the input documents and adding them to a single array of those documents.

Input: `a`, `b`, `c`\
Output: `[a, b, c]`

Where:\
a: `{"number": 1}`\
b: `{"number": 2}`\
c: `{"number": 3}`

Becomes:

```json
[{ "number": 1 }, { "number": 2 }, { "number": 3 }]
```

The use of "merge" here could be mistaken in that you may expect the following output:

```json
{
  "number": 3
}
```

If you are looking for the 2nd output above, see the [merge feature request](https://github.com/TomWright/dasel/issues/133).


# Supported file types

Dasel attempts to find the correct parser for the given file type, but if that fails you can choose which parser to use with the `-p` or `--parser` flag.

## JSON

```shell
-p json
```

Using [golang.org/pkg/encoding/json](https://golang.org/pkg/encoding/json/).

### **Multi-document files**

Multi-document files are decoded into an array, with `[0]` being the first document, `[1]` being the second and so on.

Once decoded, you can access them using any of the standard selectors provided by Dasel.

## TOML

```shell
-p toml
```

Using [github.com/pelletier/go-toml](https://github.com/pelletier/go-toml).

## YAML

```shell
-p yaml
```

Using [gopkg.in/yaml.v2](https://gopkg.in/yaml.v2).

### **Multi-document files**

Multi-document files are decoded into an array, with `[0]` being the first document, `[1]` being the second and so on.

Once decoded, you can access them using any of the standard selectors provided by Dasel.

## XML

```shell
-p xml
```

Using [github.com/clbanning/mxj](https://github.com/clbanning/mxj).

### **Data Format**

XML documents within dasel are stored as a map of values.

This is just how dasel stores data and is required for the general functionality to work. An example of a simple documents representation is as follows:

```markup
<Person active="true">
  <Name main="yes">Tom</Name>
  <Age>27</Age>
</Person>
```

```go
map[
  Person:map[
    -active:true
    Age:27
    Name:map[
      #text:Tom
      -main:true
    ]
  ]
]
```

In general this won't affect you, but on the odd occasion in specific instances it could lead to unexpected output.

If you are struggling with this please open a [discussion](https://github.com/TomWright/dasel/discussions) for support. This will also help me know when the docs aren't sufficient.

### **Debugging**

You can run select commands with the `--plain` flag to see the raw data that is stored within dasel. This can help you figure out the exact properties you may need to target when it isn't immediately obvious.

### **Arrays/Lists**

Due to the way that XML is decoded, dasel can only detect something as a list if there are at least 2 items.

If you try to use list selectors (dynamic, index, append) when there are less than 2 items in the list you will get an error.

There are no plans to introduce a workaround for this but if there is enough demand it may be worked on in the future.

## CSV

```shell
-p csv
```

Using [golang.org/pkg/encoding/csv](https://golang.org/pkg/encoding/csv/).

### **Adding data**

New columns will be detected and added to the end of the CSV output.

Column deletion is not supported.

## Plain

```shell
-p plain
```

This outputs the data using `fmt.Sprint(x)`, displaying whatever underlying value is present as a string.


# Introduction

## Description

Selectors define a path through a set of data.

Selectors are made up of different parts separated by a dot `.`, each part being used to identify the next node in the chain.

## Escaping

You can escape values in selectors using a backslash `\`. The main use for this is to allow you to target fields that contain a dot or space in their name.


# Property

## Description

A property selector is the most common selector, and is used to select a specific named property within a map.

## Usage

```shell
.propertyName
```

## Example

```shell
$ echo '{"name": "Tom"}' | dasel -p json '.name'
Tom
```


# Keys and indexes

## Description

The key/index selector is used to return a list of all keys/indexes in the current node.

## Usage

{% hint style="info" %}
This must be used in conjunction with the `-m`, `--multiple` flag.
{% endhint %}

```shell
.-
```

## Example

```shell
$ echo '{"a":{"c": [1, 2, 3]},"b":{}}' | dasel -p json -m '.a.c.-'
"0"
"1"
"2"
```


# Index

## Description

The index selector allows you to access a specific element of an array.

## Usage

```shell
.[0]
```

## Example

```shell
$ echo '{"a":{"b": [1, 2, 3]}}' | dasel -p json '.a.b.[1]'
"2"
```


# Next Available Index

## Description

The next available index selector allows you to target the next available index of an array.

You can think of this as appending to a list.

## Usage

{% hint style="info" %}
This is only available in [put](/v1/usage/put) commands.
{% endhint %}

```shell
.[]
```

## Example

```shell
$ echo '{"x": [1, 2]}' | dasel put int -p json '.x.[]' 3
{
  "x": [
    1,
    2,
    3
  ]
}
```


# All indexes

## Description

The all indexes selector allows you to target all items of a list or map.

## Usage

{% hint style="info" %}
This must be used in conjunction with the `-m`, `--multiple` flag.
{% endhint %}

```shell
.[*]
```

## Example

### Array

```shell
$ echo '{"x": [1, 2, 3]}' | dasel select -m -p json '.x.[*]'
1
2
3
```

### Object/Map

```shell
$ echo '{"x": {"x": 1, "y": 2, "z": 3}}' | dasel select -m -p json '.x.[*]'
1
2
3
```


# Dynamic

## Description

Dynamic selectors allow you to select items from lists or maps when you don't know the key or index. You can think of this as searching the current node.

## Usage

{% hint style="info" %}
You can use a selector as the key to create more complex conditions.
{% endhint %}

```shell
.(<key>=<value>)
```

### Key

The key defines which property/selector we should use to extract a value.

If `<key>` is:

* `.` or `value` - dasel checks if the current nodes value is `<value>`.
* `-` or `keyValue` - dasel checks if the key/name/index of the current node is `<value>`.
* Else dasel uses the key as a selector itself and compares the result against `<value>`.

### Value

The value is the expected value for the check to pass.

Note that dasel will stringy values prior to checking if they match.

### Comparisons

Dasel supports the following comparison operators:

| Operator | Supported since |
| -------- | --------------- |
| `=`      | `v0.0.4`        |
| `>=`     | `v1.14.0`       |
| `>`      | `v1.14.0`       |
| `<`      | `v1.14.0`       |
| `<=`     | `v1.14.0`       |
| `!=`     | `v1.17.0`       |

### Multiple conditions

You can use multiple dynamic selectors within the same part to perform `AND` logic.

```shell
.(<key>=<value>)(<key2>=<value2>)
```

### Non-object values

You can evaluate and check against non-object values by defining the `key` as either `value` or `.`. Doing so will tell dasel extract the value of the current node and compare that against `<value>`.

### Selectors as a key

When performing dynamic checks dasel internally creates a new root node at the current position and queries data from there.

This means that you can use fully formed selectors as a key to create more advanced logic.

```shell
.users.(.addresses.(.primary=true).number=123).name.first
```

The above selector in plain English may read as...

> Give me the first name of the user who's primary address is at number 123.

The resolution of that query looks something like this:

```
.users.(.addresses.(.primary=true).number=123).name.first
.users.(.addresses.[0].number=123).name.first
.users.[0].name.first
```

## Example

{% code title="simple:input.yaml" %}

```yaml
colourCodes:
  - name: red
    rgb: ff0000
  - name: green
    rgb: 00ff00
  - name: blue
    rgb: 0000ff
```

{% endcode %}

{% code title="advanced:input.json" %}

```json
{
  "users": [
    {
      "name": {
        "first": "Tom",
        "last": "Wright"
      },
      "addresses": [
        {
          "primary": true,
          "number": 123
        },
        {
          "primary": false,
          "number": 456
        }
      ]
    }
  ]
}
```

{% endcode %}

### Single condition

```shell
$ dasel select -f simple_input.yaml '.colourCodes.(name=red).rgb'
ff0000
```

### Multiple conditions

```shell
$ dasel select -f simple_input.yaml '.colourCodes.(name=red)(rgb=ff0000).rgb'
ff0000
```

### Selector as a key

```shell
$ dasel -f advanced_input.json '.users.(.addresses.(.primary=true).number=123).name.first'
"Tom"
```


# Search

## Description

Search selectors recursively search all the data below the current node and return all of the results.

## Usage

{% hint style="info" %}
This must be used in conjunction with the `-m`, `--multiple` flag.
{% endhint %}

```shell
.(?:<key>=<value>)
```

### Key

The key defines which property/selector we should use to extract a value.

If `<key>` is:

* `.` or `value` - dasel checks if the current nodes value is `<value>`.
* `-` or `keyValue` - dasel checks if the key/name/index of the current node is `<value>`.
* Else dasel uses the key as a selector itself and compares the result against `<value>`.

### Value

The value is the expected value for the check to pass.

Note that dasel will stringy values prior to checking if they match.

### Comparisons

Dasel supports the following comparison operators:

| Operator | Supported since |
| -------- | --------------- |
| `=`      | `v1.6.0`        |
| `!=`     | `v1.17.0`       |

## Example

{% code title="input.json" %}

```json
{
  "users": [
    {
      "primary": true,
      "name": {
        "first": "Tom",
        "last": "Wright"
      }
    },
    {
      "primary": false,
      "extra": {
        "name": {
          "first": "Joe",
          "last": "Blogs"
        }
      },
      "name": {
        "first": "Jim",
        "last": "Wright"
      }
    }
  ]
}
```

{% endcode %}

### Search by key name

```shell
$ dasel select -f input.json -m '.(?:-=name).first'
"Tom"
"Joe"
"Jim"
```

### Search by selector

```shell
$ dasel select -f input.json -m '.(?:.name.last=Wright).name.first'
"Tom"
"Jim"
```


# Search Optional

## Description

Search optional selectors recursively search all the data below the current node and return all of the results.

This differs from search in that the query does not fail when the field you filter on does not exist.

{% hint style="info" %}
Available since `v1.26.0.`
{% endhint %}

## Usage

{% hint style="info" %}
This must be used in conjunction with the `-m`, `--multiple` flag.
{% endhint %}

```shell
.(#:<key>=<value>)
```

### Key

The key defines which property/selector we should use to extract a value.

If `<key>` is:

* `.` or `value` - dasel checks if the current nodes value is `<value>`.
* `-` or `keyValue` - dasel checks if the key/name/index of the current node is `<value>`.
* Else dasel uses the key as a selector itself and compares the result against `<value>`.

### Value

The value is the expected value for the check to pass.

Note that dasel will stringy values prior to checking if they match.

### Comparisons

Dasel supports the following comparison operators:

| Operator | Supported since |
| -------- | --------------- |
| `=`      | `v1.6.0`        |
| `!=`     | `v1.17.0`       |

## Example

{% code title="input.json" %}

```json
{
  "users": [
    {
      "primary": true,
      "name": {
        "first": "Tom",
        "last": "Wright"
      }
    },
    {
      "primary": false,
      "name": {
        "first": "Jim",
        "last": "Wright"
      }
    },
    {
      "name": {
        "first": "Frank",
        "last": "Wright"
      }
    }
  ]
}
```

{% endcode %}

### Search by optional property

```shell
$ dasel select -f input.json -m '.users.(#:primary=true).name.first'
"Tom"
```


# Length

## Description

The length selector can be used to return the length of the current node.

## Usage

```
.[#]
```

### Supported types

The length selector can be used on the following data types:

* Array/slice
* Map/object
* String

## Example

```shell
$ echo '{"numbers": [5, 2, 3, 1, 4]}' | dasel -p json '.numbers.[#]'
5
```


# Type

## Description

The type selector can be used to return the type of the current node.

## Usage

```
.[@]
```

### Return types

The type selector can return the following types:

* `array`
* `map`
* `string`
* `int`
* `float`
* `bool`

## Example

```shell
$ echo '{"numbers": [5, 2, 3, 1, 4]}' | dasel -r json '.[@]'
"map"
```

```shell
$ echo '{"numbers": [5, 2, 3, 1, 4]}' | dasel -r json '.numbers.[@]'
"array"
```

```shell
$ echo '{"numbers": [5, 2, 3, 1, 4]}' | dasel -r json '.numbers.[0].[@]'
"float"
```


# File formatting and ordering

The formatting of files can be changed while being processed. Dasel itself doesn't make these changes, rather the act of marshaling the results.

In short, the output files may have properties in a different order but the actual contents will be as expected.


# Memory usage

Dasel's method of querying data requires that the entire input document is stored in memory.

You should keep this in mind as the maximum file size it can process will be limited by your system's available resources (specifically RAM).


# Converting between formats

{% hint style="info" %}
See [supported file types](/v1/usage/supported-file-types) for a list of available formats.
{% endhint %}

Dasel allows you to specify different input/output formats using the `-r`,`--read` and `-w`,`--write` flags.

```shell
$ echo '{"name": "Tom"}{"name": "Jim"}' | dasel -r json -w yaml .
name: Tom
---
name: Jim
```

This works well in general but you may run into issues when converting between data formats that don't typically play well together.

If you have any questions or concerns around this please raise a [discussion](https://github.com/TomWright/dasel/discussions).


# JQ to Dasel

The follow examples show a set of [jq](https://github.com/stedolan/jq) commands and the equivalent in dasel.

### **Select a single value**

{% tabs %}
{% tab title="JQ" %}

```shell
echo '{"name": "Tom"}' | jq '.name'
"Tom"
```

{% endtab %}

{% tab title="Dasel" %}

```shell
echo '{"name": "Tom"}' | dasel -p json '.name'
"Tom"
```

{% endtab %}
{% endtabs %}

### **Select a nested value**

{% tabs %}
{% tab title="JQ" %}

```shell
echo '{"user": {"name": "Tom", "age": 27}}' | jq '.user.age'
27
```

{% endtab %}

{% tab title="Dasel" %}

```shell
echo '{"user": {"name": "Tom", "age": 27}}' | dasel -p json '.user.age'
27
```

{% endtab %}
{% endtabs %}

### **Select an array index**

{% tabs %}
{% tab title="JQ" %}

```shell
echo '[1, 2, 3]' | jq '.[1]'
2
```

{% endtab %}

{% tab title="Dasel" %}

```shell
echo '[1, 2, 3]' | dasel -p json '.[1]'
2
```

{% endtab %}
{% endtabs %}

### **Append to an array of strings**

{% tabs %}
{% tab title="JQ" %}

```shell
echo '["a", "b", "c"]' | jq '. += ["d"]'
[
  "a",
  "b",
  "c",
  "d"
]
```

{% endtab %}

{% tab title="Dasel" %}

```shell
echo '["a", "b", "c"]' | dasel put string -p json -s '.[]' d
[
  "a",
  "b",
  "c",
  "d"
]
```

{% endtab %}
{% endtabs %}

### **Update a string value**

{% tabs %}
{% tab title="JQ" %}

```shell
echo '["a", "b", "c"]' | jq '.[1] = "d"'
[
  "a",
  "d",
  "c"
]
```

{% endtab %}

{% tab title="Dasel" %}

```shell
echo '["a", "b", "c"]' | dasel put string -p json '.[1]' d
[
  "a",
  "d",
  "c"
]
```

{% endtab %}
{% endtabs %}

### **Update an int value**

{% tabs %}
{% tab title="JQ" %}

```shell
echo '[1, 2, 3]' | jq '.[1] = 5'
[
  1,
  5,
  3
]
```

{% endtab %}

{% tab title="Dasel" %}

```shell
echo '[1, 2, 3]' | dasel put int -p json '.[1]' 5
[
  1,
  5,
  3
]
```

{% endtab %}
{% endtabs %}

### **Overwrite an object**

{% tabs %}
{% tab title="JQ" %}

```shell
echo '{"user": {"name": "Tom", "age": 27}}' | jq '.user = {"name": "Frank", "age": 25}'
{
  "user": {
    "name": "Frank",
    "age": 25
  }
}
```

{% endtab %}

{% tab title="Dasel put object" %}

```shell
echo '{"user": {"name": "Tom", "age": 27}}' | dasel put object -p json -t string -t int '.user' name=Frank age=25
{
  "user": {
    "age": 25,
    "name": "Frank"
  }
}
```

{% endtab %}

{% tab title="Dasel put document" %}

```shell
echo '{"user": {"name": "Tom", "age": 27}}' | dasel put document -p json '.user' '{"name": "Frank", "age": 25}'
{
  "user": {
    "age": 25,
    "name": "Frank"
  }
}
```

{% endtab %}
{% endtabs %}

### **Append to an array of objects**

{% tabs %}
{% tab title="Bash" %}

```shell
echo '{"users": [{"name": "Tom"}]}' | jq '.users += [{"name": "Frank"}]'
{
  "users": [
    {
      "name": "Tom"
    },
    {
      "name": "Frank"
    }
  ]
}
```

{% endtab %}

{% tab title="Dasel put object" %}

```shell
echo '{"users": [{"name": "Tom"}]}' | dasel put object -p json -t string '.users.[]' name=Frank
{
  "users": [
    {
      "name": "Tom"
    },
    {
      "name": "Frank"
    }
  ]
}
```

{% endtab %}

{% tab title="Dasel put document" %}

```shell
echo '{"users": [{"name": "Tom"}]}' | dasel put document -p json '.users.[]' '{"name":"Frank"}'
{
  "users": [
    {
      "name": "Tom"
    },
    {
      "name": "Frank"
    }
  ]
}
```

{% endtab %}
{% endtabs %}


# YQ to Dasel

The follow examples show a set of [yq](https://github.com/kislyuk/yq) commands and the equivalent in dasel.

### **Select a single value**

{% tabs %}
{% tab title="YQ" %}

```shell
echo 'name: Tom' | yq '.name'
"Tom"
```

{% endtab %}

{% tab title="Dasel" %}

```shell
echo 'name: Tom' | dasel -p yaml '.name'
Tom
```

{% endtab %}
{% endtabs %}

### **Select a nested value**

{% tabs %}
{% tab title="YQ" %}

```shell
echo 'user:
  name: Tom
  age: 27' | yq '.user.age'
27
```

{% endtab %}

{% tab title="Dasel" %}

```shell
echo 'user:
       name: Tom
       age: 27' | dasel -p yaml '.user.age'
27
```

{% endtab %}
{% endtabs %}

### **Select an array index**

{% tabs %}
{% tab title="YQ" %}

```shell
echo '- 1
- 2
- 3' | yq '.[1]'
2
```

{% endtab %}

{% tab title="Dasel" %}

```shell
echo '- 1
- 2
- 3' | dasel -p yaml '.[1]'
2
```

{% endtab %}
{% endtabs %}

### **Append to an array of strings**

{% tabs %}
{% tab title="YQ" %}

```shell
echo '- a
- b
- c' | yq --yaml-output '. += ["d"]'
- a
- b
- c
- d
```

{% endtab %}

{% tab title="Dasel" %}

```shell
echo '- a
- b
- c' | dasel put string -p yaml -s '.[]' d
- a
- b
- c
- d
```

{% endtab %}
{% endtabs %}

### **Update a string value**

{% tabs %}
{% tab title="YQ" %}

```shell
echo '- a
- b
- c' | yq --yaml-output '.[1] = "d"'
- a
- d
- c
```

{% endtab %}

{% tab title="Dasel" %}

```shell
echo '- a
- b
- c' | dasel put string -p yaml -s '.[1]' d
- a
- d
- c
```

{% endtab %}
{% endtabs %}

### **Update an int value**

{% tabs %}
{% tab title="YQ" %}

```shell
echo '- 1
- 2
- 3' | yq --yaml-output '.[1] = 5'
- 1
- 5
- 3
```

{% endtab %}

{% tab title="Dasel" %}

```
echo '- 1
- 2
- 3' | dasel put int -p yaml -s '.[1]' 5
- 1
- 5
- 3
```

{% endtab %}
{% endtabs %}

### **Overwrite an object**

{% tabs %}
{% tab title="YQ" %}

```shell
echo 'user:
  name: Tom
  age: 27' | yq --yaml-output '.user = {"name": "Frank", "age": 25}'
user:
  name: Frank
  age: 25
```

{% endtab %}

{% tab title="Dasel put object" %}

```shell
echo 'user:
  name: Tom
  age: 27' | dasel put object -p yaml -t string -t int '.user' name=Frank age=25
user:
  age: 25
  name: Frank
```

{% endtab %}

{% tab title="Dasel put document" %}

```shell
echo 'user:
  name: Tom
  age: 27' | dasel put document -p yaml -d json '.user' '{"name":"Frank","age":25}'
user:
  age: 25
  name: Frank
```

{% endtab %}
{% endtabs %}

### **Append to an array of objects**

{% tabs %}
{% tab title="YQ" %}

```shell
echo 'users:
- name: Tom' | yq --yaml-output '.users += [{"name": "Frank"}]'
users:
  - name: Tom
  - name: Frank
```

{% endtab %}

{% tab title="Dasel put object" %}

```shell
echo 'users:
- name: Tom' | dasel put object -p yaml -t string '.users.[]' name=Frank
users:
- name: Tom
- name: Frank
```

{% endtab %}

{% tab title="Dasel put document" %}

```shell
echo 'users:
- name: Tom' | dasel put document -p yaml -d json '.users.[]' '{"name":"Frank"}'
users:
- name: Tom
- name: Frank
```

{% endtab %}
{% endtabs %}


# XML

XML has some slight differences (such as attributes) that should be documented.

See [XML file format](/v1/usage/supported-file-types#xml) for more information.

## **Query attributes**

Decoded attributes are set as properties on the related object with a prefix of `-`.

```shell
echo '<data>
    <users primary="true">
        <name>Tom</name>
    </users>
    <users primary="false">
        <name>Frank</name>
    </users>
</data>' | dasel -p xml '.data.users.[0].-primary'
true
```

## **Filtering on attributes**

We can also filter on attributes since they are defined against the related object.

```shell
echo '<data>
    <users primary="true">
        <name>Tom</name>
    </users>
    <users primary="false">
        <name>Frank</name>
    </users>
</data>' | dasel -p xml '.data.users.(-primary=true).name'
Tom
```


# Filter JSON API results

The following line will return the download URL for the latest macOS dasel release:

```
$ curl https://api.github.com/repos/tomwright/dasel/releases/latest | dasel -p json --plain '.assets.(name=dasel_darwin_amd64).browser_download_url'

https://github.com/TomWright/dasel/releases/download/v1.13.6/dasel_darwin_amd64
```


# Introduction

{% hint style="warning" %}
You are viewing dasel v2 documentation.
{% endhint %}

## Introduction

Dasel (short for data-selector) allows you to query and modify data structures using selector strings.

### One tool to rule them all <a href="#one-tool-to-rule-them-all" id="one-tool-to-rule-them-all"></a>

Say good bye to learning new tools just to work with a different data format.Dasel uses a standard selector syntax no matter the data format. This means that once you learn how to use dasel you immediately have the ability to query/modify any of the supported data types without any additional tools or effort.

## V1 to V2 breaking changes

This release does introduce a major version upgrade, and as such there are breaking changes.

### Select command

The select command remains largely the same, but the selector format has changed a lot. See selector changes below.

* Removal of `-p`,`--parser`. Please use `-r`,`--read` and `-w`,`--write`.
  * Note that if no `-w` is given, the value of `-r` is used.
  * `dasel -p json ...` becomes `dasel -r json ...`
* Removal of `--format` flag.
  * I plan on implementing this as a custom write parser instead.
* Removal of `-m`,`--multi` flag. All selectors now act in this manner.
* Removal of `-c`, `--compact` flag. Use `--pretty=false` instead.

### Put command

* Removal of sub commands (e.g. `dasel put string`).
  * Dasel now expects a `dasel put` command to have a `-t`,`--type` flag that specified the type.
  * If the given type doesn't match a pre-defined type (`string`, `int`, etc) it is checked against the read parsers (e.g. `json`, `yaml`). This is how you can achieve the previous `put document` functionality.
* Complete removal of `dasel put object`. Please use `dasel put -t json` or similar to achieve the same outcome.
* Removal of `-p`,`--parser`. Please use `-r`,`--read` and `-w`,`--write`.
  * Note that if no `-w` is given, the value of `-r` is used.
  * `dasel -p json ...` becomes `dasel -r json ...`
* Removal of `-m`,`--multi` flag. All selectors now act in this manner.
* Removal of `-c`, `--compact` flag. Use `--pretty=false` instead.

### Delete command

The delete command remains largely the same, but the selector format has changed a lot. See selector changes below.

* Removal of `-p`,`--parser`. Please use `-r`,`--read` and `-w`,`--write`.
  * Note that if no `-w` is given, the value of `-r` is used.
  * `dasel -p json ...` becomes `dasel -r json ...`
* Removal of `-m`,`--multi` flag. All selectors now act in this manner.
* Removal of `-c`, `--compact` flag. Use `--pretty=false` instead.

### Update command

The self-update functionality within dasel has been completely removed. Please use package managers to achieve this functionality.

### Selector changes

Dasel selectors have been completely reworked.

The purpose of this is to allow users to build their own complex logic and filtering without needing specific code being written to handle their use-case.

Please see the [function overview](/v2/functions/selector-overview) for function documentation and examples.


# Supported file formats

Dasel supports the following file formats:

* `json`
* `yaml`
  * Merge tags/aliases are supported in reads from `v2.8.0`.
* `csv`
* `toml` [v1.0.0](https://toml.io/en/v1.0.0)
* `xml`
* `-` (plain, write-only)

Note that

* Some format specific features such as comments may not be present in dasel output.
* Array ordering is not guaranteed. The JSON spec for example doesn't guarantee ordering. As a result dasel cannot either.
* The plain (`-`) parser can only be used when writing.


# Memory usage

Dasel does not perform partial reads or streaming. As a result the dasel executable will read the entire given document into memory.

You should be aware that dasel will attempt to allocate a lot of memory if you are processing very large documents.


# Installation

## Homebrew

The easiest way to get your hands on the latest version of dasel is to use homebrew:

```shell
brew install dasel
```

## Docker

Run dasel in docker using the image `ghcr.io/tomwright/dasel`.

### Usage

Run the docker image, passing in a dasel command with the executable excluded.

```shell
$ echo '{"name": "Tom"}' | docker run -i --rm ghcr.io/tomwright/dasel:latest -r json '.name'
"Tom"
```

### Versioning

New image versions are built and pushed automatically as part of the CI/CD pipeline in Github actions.

| Tag           | Description                                 |
| ------------- | ------------------------------------------- |
| `latest`      | The latest release version.                 |
| `development` | The latest build from `master` branch.      |
| `v*.*.*`      | The specified dasel release. E.g. `v2.0.0`. |

## ASDF

Using [asdf-vm](https://asdf-vm.com) and the [asdf-dasel plugin](https://github.com/asdf-community/asdf-dasel?ts=4).

```shell
asdf plugin add dasel https://github.com/asdf-community/asdf-dasel.git
asdf list all dasel
asdf install dasel <version>
asdf global dasel <version>
```

## Mise

Using [mise](https://github.com/jdx/mise).

List dasel versions available:

```shell
mise ls-remote dasel
```

Install a specific version (you can use the latest alias) and make it available globally:

```shell
mise install dasel@<version>
mise use -g dasel@<version>
```

## Nix

To install using the [Nix Package Manager](https://nixos.org) (for non-NixOS)

```shell
nix-env -iA nixpkgs.dasel
```

Or NixOS:

```shell
nix-env -iA nixos.dasel
```

## Windows

See [manual install](#manual).

## Manual

You can download a compiled executable from the [latest release](https://github.com/TomWright/dasel/releases/latest).

{% hint style="info" %}
Don't forget to put the binary somewhere in your `PATH`.
{% endhint %}

{% tabs %}
{% tab title="Linux (64 bit)" %}

```
curl -sSLf "$(curl -sSLf https://api.github.com/repos/tomwright/dasel/releases/latest | grep browser_download_url | grep linux_amd64 | grep -v .gz | cut -d\" -f 4)" -L -o dasel && chmod +x dasel
mv ./dasel /usr/local/bin/dasel
```

{% endtab %}

{% tab title="Mac OS (64 bit)" %}

```
curl -sSLf "$(curl -sSLf https://api.github.com/repos/tomwright/dasel/releases/latest | grep browser_download_url | grep -v .gz | grep darwin_amd64 | cut -d\" -f 4)" -L -o dasel && chmod +x dasel
mv ./dasel /usr/local/bin/dasel
```

{% endtab %}

{% tab title="Windows" %}

```powershell
$releases = curl -sSLf https://api.github.com/repos/tomwright/dasel/releases/latest
Invoke-WebRequest -Uri (($releases | ConvertFrom-Json).assets `
                    | Where-Object { $_.name -eq "dasel_windows_amd64.exe" } `
                    | Select-Object -ExpandProperty browser_download_url) `
                    -OutFile dasel.exe
```

{% endtab %}
{% endtabs %}

## Scoop

Use the scoop command-line installer to install dasel on windows 10.

```shell
scoop bucket add extras
scoop install dasel
```

## Development Version

You can `go install` the `cmd/dasel` package to build and install dasel for you.

{% hint style="info" %}
You may need to prefix the command with `GO111MODULE=on` in order for this to work.
{% endhint %}

```
go install github.com/tomwright/dasel/v2/cmd/dasel@master
```


# Select

Select is the default command for the `dasel` cli.

The select command allows you to select data from any supported data structure.

## Usage

```
$ echo '{"name":{"first":"Tom","last":"Wright"}}' | dasel -r json 'name.first'
"Tom"
```

See the [function documentation](/v2/functions/selector-overview) for information on the available selectors.

## Flags/Args

<table><thead><tr><th>Flag</th><th>Type</th><th width="249.33333333333331">Description</th><th>Default</th></tr></thead><tbody><tr><td><code>--colour</code></td><td><code>bool</code></td><td>Print colourised output.</td><td><code>false</code></td></tr><tr><td><code>--escape-html</code></td><td><code>bool</code></td><td>Escape HTML tags when writing output.</td><td><code>false</code></td></tr><tr><td><code>-f</code>, <code>--file</code></td><td><code>string</code></td><td>The file to query.<br>If no file is given dasel reads from <code>stdin</code>.</td><td></td></tr><tr><td><code>--pretty</code></td><td><code>bool</code></td><td>Pretty print the output.</td><td><code>true</code></td></tr><tr><td><code>-r</code>, <code>--read</code></td><td><code>string</code></td><td>The parser to use when reading.<br>If no parser is given dasel attempts to find a parser from the <code>--file</code> flag.</td><td></td></tr><tr><td><code>-s</code>, <code>--selector</code></td><td><code>string</code></td><td>The selector used to query the input data.<br>If no flag is given dasel attempts to use the first argument as the selector.</td><td></td></tr><tr><td><code>-w</code>, <code>--write</code></td><td><code>string</code></td><td>The parser to use when writing.<br>If no parser is given dasel will use the <code>--read</code> flag.</td><td></td></tr><tr><td><code>--csv-comma</code></td><td><code>string</code></td><td>The separator used when working with csv files.</td><td><code>,</code></td></tr><tr><td><code>--csv-write-comma</code></td><td><code>string</code></td><td>The separator used when writing csv files.</td><td>value of <code>--csv-comma</code> </td></tr><tr><td><code>--csv-comment</code></td><td><code>string</code></td><td>The comment character used when working with csv files.</td><td></td></tr><tr><td><code>--csv-crlf</code></td><td><code>bool</code></td><td>True to write csv files with a <code>\r\n</code> instead of <code>\n.</code></td><td><code>false</code></td></tr></tbody></table>


# Put

The put command allows you to modify data in any supported data structure.

## Usage

```
$ echo '{"name":{"first":"Tom","last":"Wright"}}' |
  dasel put -r json -t string -v Frank 'name.first'
{
  "name": {
    "first": "Frank",
    "last": "Wright"
  }
}
```

See the [function documentation](/v2/functions/selector-overview) for information on the available selectors.

## Flags/Args

<table><thead><tr><th width="214">Flag</th><th width="128">Type</th><th width="308.3333333333333">Description</th><th>Default</th></tr></thead><tbody><tr><td><code>--colour</code></td><td><code>bool</code></td><td>Print colourised output.</td><td><code>false</code></td></tr><tr><td><code>--escape-html</code></td><td><code>bool</code></td><td>Escape HTML tags when writing output.</td><td><code>false</code></td></tr><tr><td><code>-f</code>, <code>--file</code></td><td><code>string</code></td><td>The file to query.<br>If no file is given dasel reads from <code>stdin</code>.</td><td></td></tr><tr><td><code>-o</code>, <code>--out</code></td><td><code>string</code></td><td>The file to write results to.<br>If no file is given dasel writes to <code>--file</code>.<br>If <code>--file</code> is <code>stdin</code>, dasel writes to <code>stdout</code>.</td><td></td></tr><tr><td><code>--pretty</code></td><td><code>bool</code></td><td>Pretty print the output.</td><td><code>true</code></td></tr><tr><td><code>-r</code>, <code>--read</code></td><td><code>string</code></td><td>The parser to use when reading.<br>If no parser is given dasel attempts to find a parser from the <code>--file</code> flag.</td><td></td></tr><tr><td><code>-s</code>, <code>--selector</code></td><td><code>string</code></td><td>The selector used to query the input data.<br>If no flag is given dasel attempts to use the first argument as the selector.</td><td></td></tr><tr><td><code>-t</code>, <code>--type</code></td><td><code>string</code></td><td>The type of value we are writing.<br>Can be <code>string</code>, <code>int</code> or <code>bool</code>. If it is not contained in that list dasel attempts to find a read parser of <code>--type</code> and if found will read the input value as a document.</td><td></td></tr><tr><td><code>-v</code>, <code>--value</code></td><td><code>string</code></td><td>The value to write.<br>This must be a string input but dasel will parse/convert the value to the given <code>--type</code> internally.</td><td></td></tr><tr><td><code>-w</code>, <code>--write</code></td><td><code>string</code></td><td>The parser to use when writing.<br>If no parser is given dasel attempts to find a parser from the <code>--out</code> flag.<br>If no <code>--out</code> flag is given dasel uses the <code>--read</code> flag.</td><td></td></tr><tr><td><code>--csv-comma</code></td><td><code>string</code></td><td>The separator used when working with csv files.</td><td><code>,</code></td></tr><tr><td><code>--csv-write-comma</code></td><td><code>string</code></td><td>The separator used when writing csv files.</td><td>value of <code>--csv-comma</code> </td></tr><tr><td><code>--csv-comment</code></td><td><code>string</code></td><td>The comment character used when working with csv files.</td><td></td></tr><tr><td><code>--csv-crlf</code></td><td><code>bool</code></td><td>True to write csv files with a <code>\r\n</code> instead of <code>\n.</code></td><td><code>false</code></td></tr></tbody></table>


# Delete

The delete command allows you to delete data in any supported data structure.

## Usage

```
$ echo '{"name":{"first":"Tom","last":"Wright"}}' |
  dasel delete -r json 'name.last'
{
  "name": {
    "first": "Frank"
  }
}
```

See the [function documentation](/v2/functions/selector-overview) for information on the available selectors.

## Flags/Args

<table><thead><tr><th width="214">Flag</th><th width="128">Type</th><th width="308.3333333333333">Description</th><th>Default</th></tr></thead><tbody><tr><td><code>--colour</code></td><td><code>bool</code></td><td>Print colourised output.</td><td><code>false</code></td></tr><tr><td><code>--escape-html</code></td><td><code>bool</code></td><td>Escape HTML tags when writing output.</td><td><code>false</code></td></tr><tr><td><code>-f</code>, <code>--file</code></td><td><code>string</code></td><td>The file to query.<br>If no file is given dasel reads from <code>stdin</code>.</td><td></td></tr><tr><td><code>-o</code>, <code>--out</code></td><td><code>string</code></td><td>The file to write results to.<br>If no file is given dasel writes to <code>--file</code>.<br>If <code>--file</code> is <code>stdin</code>, dasel writes to <code>stdout</code>.</td><td></td></tr><tr><td><code>--pretty</code></td><td><code>bool</code></td><td>Pretty print the output.</td><td><code>true</code></td></tr><tr><td><code>-r</code>, <code>--read</code></td><td><code>string</code></td><td>The parser to use when reading.<br>If no parser is given dasel attempts to find a parser from the <code>--file</code> flag.</td><td></td></tr><tr><td><code>-s</code>, <code>--selector</code></td><td><code>string</code></td><td>The selector used to query the input data.<br>If no flag is given dasel attempts to use the first argument as the selector.</td><td></td></tr><tr><td><code>-w</code>, <code>--write</code></td><td><code>string</code></td><td>The parser to use when writing.<br>If no parser is given dasel attempts to find a parser from the <code>--out</code> flag.<br>If no <code>--out</code> flag is given dasel uses the <code>--read</code> flag.</td><td></td></tr><tr><td><code>--csv-comma</code></td><td><code>string</code></td><td>The separator used when working with csv files.</td><td><code>,</code></td></tr><tr><td><code>--csv-write-comma</code></td><td><code>string</code></td><td>The separator used when writing csv files.</td><td>value of <code>--csv-comma</code> </td></tr><tr><td><code>--csv-comment</code></td><td><code>string</code></td><td>The comment character used when working with csv files.</td><td></td></tr><tr><td><code>--csv-crlf</code></td><td><code>bool</code></td><td>True to write csv files with a <code>\r\n</code> instead of <code>\n.</code></td><td><code>false</code></td></tr></tbody></table>


# Selector Overview

Dasel selectors are simply a list of functions to execute.

Each function:

* Is separated by a `.`
* Accepts 0 or more arguments
* Returns 0 or more values
* May have aliases defined to make them easier to use

All functions are documented with examples.


# All

All takes any list or object value and extracts each element within it, allowing you to access each of them individually.

## Examples

### Lists

```
echo '["a", "b", "c"]' | dasel -r json
[
  "a",
  "b",
  "c"
]

echo '["a", "b", "c"]' | dasel -r json 'all()'
"a"
"b"
"c"
```

### Objects

```
echo '{"x": 1, "y": 2, "z": 3}' | dasel -r json
{
  "x": 1,
  "y": 2,
  "z": 3
}

echo '{"x": 1, "y": 2, "z": 3}' | dasel -r json 'all()'
1
2
3
```

### Nested Objects

```
echo '{
  "users": [
    {
      "name": "Tom"
    },
    {
      "name": "Jim"
    }
  ]
}' | dasel -r json 'users.all().name'
"Tom"
"Jim"
```


# And

And accepts 1 or more arguments.

Dasel treats each argument as a selector and performs a query using the current value as the root.

If all of the resulting values are truthy, and returns true.


# Append

Append accepts no arguments.

It appends a new index to the input slice/array.

## Usage

Because the append function is commonly used dasel has a recognised alias of `[]` that results in a `append()` call.

## Examples

### Append an int to a list

```
$ echo '[10, 11]' | dasel put -r json -t int -v 12 'append()'
[
  10,
  11,
  12
]
```

### Append an int to a list with alias

```
$ echo '[10, 11]' | dasel put -r json -t int -v 12 '[]'
[
  10,
  11,
  12
]
```


# Count

Count will count the number of values output from the previous function.

## Examples

```
$ echo '{"numbers":[1,2,3,4,5,6,7,8,9]}' | dasel -r json 'count()'
1

$ echo '{"numbers":[1,2,3,4,5,6,7,8,9]}' | dasel -r json 'numbers.count()'
1

$ echo '{"numbers":[1,2,3,4,5,6,7,8,9]}' | dasel -r json 'numbers.all().count()'
9
```


# Equal

Expects 2 arguments.

The first argument is a dasel selector to be executed from the current value.

The second argument is a comparison value.

Returns true if the value found by the selector matches the comparison value.

## Examples

```
$ echo '{"numbers":[1,2,3,4,5,6,7,8,9]}' | dasel -r json 'equal(numbers.[0],1)'          
true
```


# Filter

Expects 1 or more arguments.

Each argument should be a selector.

Filter runs the given selectors against each value from the previous function, and if all selectors return a truthy value, the element is allowed through.

## Examples

```
$ echo '[
  {"label":"x","allow":true},
  {"label":"y","allow":false},
  {"label":"z","allow":true}
  ]' | dasel -r json 'all().filter(allow)'
{
  "allow": true,
  "label": "x"
}
{
  "allow": true,
  "label": "z"
}

```


# FilterOr

Expects 1 or more arguments.

Each argument should be a selector.

FilterOr runs the given selectors against each value from the previous function, and if any selectors return a truthy value, the element is allowed through.

## Examples

```
$ echo '[
  {"label":"x","allow":true},
  {"label":"y","allow":false},
  {"label":"z","allow":false}
  ]' | dasel -r json 'all().filterOr(allow,equal(label,y))'
{
  "allow": true,
  "label": "x"
}
{
  "allow": false,
  "label": "y"
}
```


# First

First expect no arguments.

It can be used with a list, and returns the first item in the list.

## Example

```
$ echo '["a","b","c"]' | dasel -r json 'first()'
"a"
```


# Index

Index expect 1 argument.

It can be used with a list, and returns the value at the given index list.

## Usage

Because the index function is commonly used dasel has a recognised alias of `[x]` that results in a `index(x)` call.

## Example

### Function usage

```
$ echo '["a","b","c"]' | dasel -r json 'index(1)'
"b"
```

### Alias usage

```
$ echo '["a","b","c"]' | dasel -r json '[1]'
"b"
```


# Join

Join allows you to join multiple values into a single string. This is dasels version of concatenation.

Expects 1 or more arguments.

## Arguments

The first argument is required, and is the separator used when joining the strings.

Any further arguments are optional.

If no additional arguments are given, join uses the output of the previous function as it's input and will join those values.

If additional arguments are given, join uses those values as selectors and joins the result of those selectors.

If you wish to join data with plain strings you may use the [`string`](/v2/functions/string) function.

{% hint style="info" %}
Be aware that the separator must always be a plain string and cannot contain any selector functions.
{% endhint %}

## Examples

### Join with no additional arguments

```
$ echo '{
  "name": {
    "first":"Tom",
    "last":"Wright"
  }
}' | dasel -r json 'name.all().join( )' 
"Tom Wright"
```

### Join with arguments

```
$ echo '{
  "name": {
    "first":"Tom",
    "last":"Wright"
  }
}' | dasel -r json 'name.join( ,string(Hello\\, my name is ),first,last)' 
"Hello, my name is  Tom Wright"
```


# Key

Key expect no arguments.

It returns the key of the current value, where the key is the object property or array index used to access it.

## Example

```
$ echo '{
  "list": ["x", "y", "z"],
  "object": {
    "a": "x",
    "b": "y",
    "c": "z"
  }
}' | dasel -r json 'all().all().key()'
0
1
2
"a"
"b"
"c"
```


# Keys

Keys expect no arguments.

Returns an array of keys for the current value, where the keys are either:

* Object field names
* Array indexes

## Example

```
$ echo '[1,2,3,4,5]' | dasel -r json 'keys()'
[
  0,
  1,
  2,
  3,
  4
]
```


# Last

Last expect no arguments.

It can be used with a list, and returns the last item in the list.

## Example

```
$ echo '["a","b","c"]' | dasel -r json 'last()'
"c"
```


# Len

Len expects no arguments and can be used on lists or objects. It returns the number of elements contained within the list/map.

## Examples

```
$ echo '{"numbers":[1,2,3,4,5,6,7,8,9]}' | dasel -r json 'len()'
1

$ echo '{"numbers":[1,2,3,4,5,6,7,8,9]}' | dasel -r json 'numbers.len()'
9
```


# LessThan

Expects 2 arguments.

The first argument is a dasel selector to be executed from the current value.

The second argument is a comparison value.

Returns true if the value found by the selector is less than the comparison value.

## Examples

### LessThan

```
$ echo '[1,2,3,4,5]' | dasel -r json 'all().lessThan(.,3)'
true
true
false
false
false
```

### LessThanEqual

```
$ echo '[1,2,3,4,5]' | dasel -r json 'all().or(equal(.,3),lessThan(.,3))'
true
true
true
false
false
```


# MapOf

Expects 2 or more arguments.

Expects arguments to be given in pairs, where the first argument is the property name, and the second argument is a selector that will be used to resolve the property value.

## Examples

### Filtering values into lists

```
$ echo '[1,2,3,4,5]' | 
  dasel -r json 'mapOf(lessThan,all().filter(lessThan(.,3)).merge(),moreThan,all().filter(moreThan(.,3)).merge())'
{
  "lessThan": [
    1,
    2
  ],
  "moreThan": [
    4,
    5
  ]
}

```

### Restructuring/picking specific fields

```
$ echo '[
  {
    "name": {
      "first": "Tom",
      "last": "Wright"
    },
    "title": "Mr",
    "phone": "07"
  },
  {
    "name": {
      "first": "Joe",
      "last": "Bloggs"
    },
    "title": "Mr",
    "phone": "07"
  }
]' | dasel -r json 'all().mapOf(firstName,name.first,lastName,name.last,title,title,phone,phone).merge()'
[
  {
    "firstName": "Tom",
    "lastName": "Wright",
    "phone": "07",
    "title": "Mr"
  },
  {
    "firstName": "Joe",
    "lastName": "Bloggs",
    "phone": "07",
    "title": "Mr"
  }
]
```

### Exporting specific fields to csv

```
$ echo '[
  {
    "name": {
      "first": "Tom",
      "last": "Wright"
    },
    "title": "Mr",
    "phone": "07"
  },
  {
    "name": {
      "first": "Joe",
      "last": "Bloggs"
    },
    "title": "Mr",
    "phone": "07"
  }
]' | dasel -r json -w csv 'all().mapOf(phone,phone,firstName,name.first).merge()'
firstName,phone
Tom,07
Joe,07
```


# Merge

Merge expect 0 or more arguments.

## No arguments

When called with no arguments merge takes all of the output values from the previous function and adds them to a single list.

## 1 or more arguments

When called with 1 or more arguments, the arguments are executed as a subquery on each of the output values from the previous function.

All values returned from subqueries across all input values are added to a single list.

## Examples

### Merge arguments

```
$ echo '{
  "name": {
    "first":"Tom",
    "last":"Wright"
  },
  "firstNames": [
    "Jim",
    "Bob"
  ]
}' | dasel -r json 'merge(name.first,firstNames.all()).all()' 
[
  "Tom",
  "Jim",
  "Bob"
]
```

### Merge no arguments

```
$ echo '[
  {"name": {"first": "Tom"}},
  {"name": {"first": "Jim"}},
  {"name": {"first": "Frank"}}
]' | dasel -r json 'all().name.first.merge()' 
[
  "Tom",
  "Jim",
  "Frank"
]
```


# MoreThan

Expects 2 arguments.

The first argument is a dasel selector to be executed from the current value.

The second argument is a comparison value.

Returns true if the value found by the selector is more than the comparison value.

## Examples

### MoreThan

```
$ echo '[1,2,3,4,5]' | dasel -r json 'all().moreThan(.,3)'
false
false
false
true
true
```

### MoreThanEqual

```
$ echo '[1,2,3,4,5]' | dasel -r json 'all().or(equal(.,3),moreThan(.,3))'
false
false
true
true
true
```


# Not

Expects 1 argument.

Expects the argument to be a selector that will be performed against the current value.

Returns false if the selector returns a truthy value.

Returns true if the selector returns a falsey value.

## Examples

### NotMoreThan

```
$ echo '[1,2,3,4,5]' | dasel -r json 'all().not(moreThan(.,3))'
true
true
true
false
false
```


# Or

Or accepts 1 or more arguments.

Dasel treats each argument as a selector and performs a query using the current value as the root.

If one of the resulting values are truthy, or returns true.


# OrDefault

Accepts 2 arguments.

Or default allows you to use another value or selector as a backup when the expected value isn't present.

## Examples

### Simple field selection

```
$ echo '{"name":"Tom","email":"contact@tomwright.me"}' | dasel -r json 'orDefault(phone,string(N/A))'           
"N/A"
```

### Creating a new map with defaults

```
$ echo '[
  {
    "name": "Tom",
    "email": "contact@tomwright.me"
  },
  {
    "name": "Jim",
    "phone": "+441234567890"
  }
]' | go run cmd/dasel/main.go -r json 'all().mapOf(name,name,email,orDefault(email,string(N/A)),phone,orDefault(phone,string(N/A)))'           
{
  "email": "contact@tomwright.me",
  "name": "Tom",
  "phone": "N/A"
}
{
  "email": "N/A",
  "name": "Jim",
  "phone": "+441234567890"
}

```


# Parent

Accepts no arguments.

Returns the parent of the current value.

## Examples

```
$ echo '[
  {
    "name": "Tom",
    "flags": {
      "banned": false
    }
  },
  {
    "name": "Jim",
    "flags": {
      "banned": true
    }
  },
  {
    "name": "Jess",
    "flags": {
      "banned": false
    }
  }
]' | dasel -r json 'all().flags.filter(equal(banned,true)).parent().parent().all().name'
"Tom"
"Jim"
"Jess"
```


# Property

Accepts 1 or more arguments.

Returns the values found under the given keys.

If any argument ends with a `?`, that lookup is considered optional and dasel will continue if that property is not found.

## Usage

Because property is a commonly used function, it has an alias.

If no round brackets are detected in a selector part and no other function detects it as an alias, dasel assumes it is a property name.

## Examples

### Property with optional field

```
$ echo '{"x": 1, "y": 2, "z": 3}' | dasel -r json 'property(x,y,bad?)'
1
2
```

### Property using alias

```
$ echo '{"x": 1, "y": 2, "z": 3}' | dasel -r json 'x'
1
```


# String

String is a basic function that allows you to return a plain string value.

Expects 1 argument.

If you wish to use a comma in your string you must escape it with a backslash `\,`.

## Examples

### Basic

```
$ echo '{}' | dasel -r json 'string(my string)' 
"my string"
```

### Add fixed values to maps

```
$ echo '{
  "name": "Tom Wright"
}' | dasel -r json 'mapOf(name,name,title,string(Mr))' 
{
  "name": "Tom Wright",
  "title": "Mr"
}
```


# Null

Null is a basic function that allows you to return a null value.

Expects 0 arguments.

## Examples

### Basic

```
$ echo '{}' | dasel -r json 'null()' 
null
```


# This

Accepts no arguments.

Returns the current value. Is most commonly used in comparison functions when you want to reference the value of the current element.

## Usage

`.` is an alias for `this()`.

## Examples

### This

```
$ echo '{"x": 1, "y": 2, "z": 3}' | dasel -r json 'all().this()'
1
2
3
```

### This using alias

```
$ echo '{"x": 1, "y": 2, "z": 3}' | dasel -r json 'all().'
1
2
3
```


# Type

Accepts no arguments.

Returns the type of the current value.

Possible return values are:

* `string`
* `number`
* `bool`
* `array`
* `object`
* `null`
* `unknown`

## Examples

### This

```
$ echo '[
  "x",
  false,
  true,
  1,
  1.1,
  {"x":1},
  [1]
]' | dasel -r json 'all().type()'
"string"
"bool"
"bool"
"number"
"number"
"object"
"array"
```


# Using dasel as a go package

## Getting a root node

You can convert values into something usable by `dasel` with [`dasel.ValueOf`](https://github.com/TomWright/dasel/blob/09ffcb6c1f500c1a9cd231684d7830d4c6a3a2a2/value.go#L18).

```go
myValue := map[string]any{
    "name": "Tom"
}
rootNode := dasel.ValueOf(myValue)
```

It's worth mentioning that this step isn't required because the commands listed below will do this conversion internally.

## Running commands

### [Select](https://github.com/TomWright/dasel/blob/09ffcb6c1f500c1a9cd231684d7830d4c6a3a2a2/context.go#L115)

```go
func main() {
	myValue := map[string]any{
		"firstName": "Tom",
		"lastName":  "Wright",
	}
	values, err := dasel.Select(myValue, "firstName")
	if err != nil {
		log.Fatalf("could not select: %s", err)
	}

	results := values.Interfaces()
	stringResults := make([]string, len(results))
	for k, v := range results {
		stringResults[k] = fmt.Sprint(v)
	}
	fmt.Printf("select result: %s", strings.Join(stringResults, ", "))
	// select result: Tom
}
```

### [Put](https://github.com/TomWright/dasel/blob/09ffcb6c1f500c1a9cd231684d7830d4c6a3a2a2/context.go#L127C6-L127C9)

```go
func main() {
	myValue := map[string]any{
		"firstName": "Tom",
		"lastName":  "Wright",
	}
	result, err := dasel.Put(myValue, "firstName", "Hello")
	if err != nil {
		log.Fatalf("could not select: %s", err)
	}

	fmt.Printf("original value: %v\n", myValue)
	fmt.Printf("put result: %v", result.Interface())
	// original value: map[firstName:Tom lastName:Wright]
	// put result: map[firstName:Hello lastName:Wright]
}
```

Note that if you pass a pointer, the original value also gets updated.

```go
func main() {
    myValue := map[string]any{
       "firstName": "Tom",
       "lastName":  "Wright",
    }
    result, err := dasel.Put(&myValue, "firstName", "Hello")
    if err != nil {
       log.Fatalf("could not select: %s", err)
    }

    fmt.Printf("original value: %v\n", myValue)
    fmt.Printf("put result: %v", result.Interface())
    // original value: map[firstName:Hello lastName:Wright]
    // put result: map[firstName:Hello lastName:Wright]
}
```

### [Delete](https://github.com/TomWright/dasel/blob/09ffcb6c1f500c1a9cd231684d7830d4c6a3a2a2/context.go#L143)

```go
func main() {
	myValue := map[string]any{
		"firstName": "Tom",
		"lastName":  "Wright",
	}
	result, err := dasel.Delete(myValue, "firstName")
	if err != nil {
		log.Fatalf("could not select: %s", err)
	}

	fmt.Printf("original value: %v\n", myValue)
	fmt.Printf("put result: %v", result.Interface())
	// original value: map[firstName:Tom lastName:Wright]
	// put result: map[lastName:Wright]
}
```

Note that if you pass a pointer, the original value also gets updated.

```go
func main() {
	myValue := map[string]any{
		"firstName": "Tom",
		"lastName":  "Wright",
	}
	result, err := dasel.Delete(&myValue, "firstName")
	if err != nil {
		log.Fatalf("could not select: %s", err)
	}

	fmt.Printf("original value: %v\n", myValue)
	fmt.Printf("put result: %v", result.Interface())
	// original value: map[lastName:Wright]
	// put result: map[lastName:Wright]
}
```


# Basics

## Select

```
$ echo '{"name":"Tom"}' | dasel -r json 'name'
"Tom"
```

## Put

```
$ echo '{"name":"Tom"}' | 
  dasel put -r json -t string -v 'contact@tomwright.me' 'email'
{
  "email": "contact@tomwright.me",
  "name": "Tom"
}
```

## Delete

```
$ echo '{
  "email": "contact@tomwright.me",
  "name": "Tom"
}' | dasel delete -r json 'email'
{
  "name": "Tom"
}
```


# Change file format

Dasel allows you to quickly and easily change the format of a file.

## JSON to YAML

```
$ echo '{
  "users": [
    {
      "name": "Tom"
    },
    {
      "name": "Jim"
    }
  ]
}' | dasel -r json -w yaml
users:
- name: Tom
- name: Jim
```

## YAML to CSV

```
$ echo 'users:
- name: Tom
- name: Jim' | dasel -r yaml -w csv 'users'  
name
Tom
Jim

```

## CSV to JSON

```
$ echo 'name
Tom
Jim
' | dasel -r csv -w json
[
  {
    "name": "Tom"
  },
  {
    "name": "Jim"
  }
]

```


# Filtering objects based on present/missing key

## Find users that have a non-empty `name` field.

```sh
$ echo '{
  "users": [
    {
      "name": "Tom"
    },
    {
      "name": "false"
    },
    {
      "name": true
    },
    {
      "wrong_name": "Jim"
    },
    {
      "name": ""
    }
  ]
}' | dasel -r json 'users.all().filter(name?.len())'
{
  "name": "Tom"
}
{
  "name": "false"
}
{
  "name": true
}
```

## Find users with an empty or missing `name` field.

```sh
$ echo '{
  "users": [
    {
      "name": "Tom"
    },
    {
      "name": "false"
    },
    {
      "name": true
    },
    {
      "wrong_name": "Jim"
    },
    {
      "name": ""
    }
  ]
}' | dasel -r json 'users.all().filter(not(name?.len()))'
{
  "wrong_name": "Jim"
}
{
  "name": ""
}
```

## Find users with a `name` field

```sh
$ echo '{
  "users": [
    {
      "name": "Tom"
    },
    {
      "name": "false"
    },
    {
      "name": true
    },
    {
      "wrong_name": "Jim"
    },
    {
      "name": ""
    }
  ]
}' | dasel -r json 'users.all().filter(keys().all().filter(equal(.,name)))'
{
  "name": "Tom"
}
{
  "name": "false"
}
{
  "name": true
}
{
  "name": ""
}
```

## Find users without a `name` field

```shell
$ echo '{
  "users": [
    {
      "name": "Tom"
    },
    {
      "name": "false"
    },
    {
      "name": true
    },
    {
      "wrong_name": "Jim"
    },
    {
      "name": ""
    }
  ]
}' | dasel -r json 'users.all().filter(not(keys().all().filter(equal(.,name)).len()))'
{
  "wrong_name": "Jim"
}
```


# Introduction

{% hint style="info" %}
Dasel V3 was released in December 2025. Please raise any issues on [GitHub](https://github.com/TomWright/dasel).
{% endhint %}

<figure><img src="/files/b8kNm9tldDDcIaP6fi3A" alt="Dasel mascot" width="375"><figcaption></figcaption></figure>

Dasel (short for **Data-Select**) is a command-line tool and library for querying, modifying, and transforming data structures such as JSON, YAML, TOML, XML, CSV, and KDL.

It provides a consistent , powerful syntax to traverse and update data - making it useful for developers, DevOps, and data wrangling tasks.

## Features

* **Multi-format support**: JSON, YAML, TOML, XML, CSV, HCL, INI, KDL.
* **Unified query syntax**: Access data in any format with the same selectors.
* **Query & search**: Extract values, lists, or structures with intuitive syntax.
* **Modify in place**: Update, insert, or delete values directly in structured files.
* **Convert between formats**: Seamlessly transform data from JSON → YAML, TOML → JSON, etc.
* **Script-friendly**: Simple CLI integration for shell scripts and pipelines.
* **Library support**: Import and use in Go projects.


# Installation

## Homebrew

The easiest way to get your hands on the latest version of dasel is to use homebrew:

```shell
brew install dasel
```

## Docker

Run dasel in docker using the image `ghcr.io/tomwright/dasel`.

### Usage

Run the docker image, passing in a dasel command with the executable excluded.

```shell
$ echo '{"name": "Tom"}' | docker run -i --rm ghcr.io/tomwright/dasel:latest -i json 'name'
"Tom"
```

### Versioning

New image versions are built and pushed automatically as part of the CI/CD pipeline in Github actions.

| Tag           | Description                                 |
| ------------- | ------------------------------------------- |
| `latest`      | The latest release version.                 |
| `development` | The latest build from `master` branch.      |
| `v*.*.*`      | The specified dasel release. E.g. `v2.0.0`. |

## ASDF

Using [asdf-vm](https://asdf-vm.com) and the [asdf-dasel plugin](https://github.com/asdf-community/asdf-dasel?ts=4).

```shell
asdf plugin add dasel https://github.com/asdf-community/asdf-dasel.git
asdf list all dasel
asdf install dasel <version>
asdf global dasel <version>
```

### Mise

Using [mise](https://github.com/jdx/mise).

List dasel versions available:

```shell
mise ls-remote dasel
```

Install a specific version (you can use the latest alias) and make it available globally:

```shell
mise install dasel@<version>
mise use -g dasel@<version>
```

## Nix

To install using the [Nix Package Manager](https://nixos.org) (for non-NixOS)

```shell
nix-env -iA nixpkgs.dasel
```

Or NixOS:

```shell
nix-env -iA nixos.dasel
```

## Windows

See [manual install](#manual).

## Manual

You can download a compiled executable from the [latest release](https://github.com/TomWright/dasel/releases/latest).

{% hint style="info" %}
Don't forget to put the binary somewhere in your `PATH`.
{% endhint %}

{% tabs %}
{% tab title="Linux (64 bit)" %}

```
curl -sSLf "$(curl -sSLf https://api.github.com/repos/tomwright/dasel/releases/latest | grep browser_download_url | grep linux_amd64 | grep -v .gz | cut -d\" -f 4)" -L -o dasel && chmod +x dasel
mv ./dasel /usr/local/bin/dasel
```

{% endtab %}

{% tab title="Mac OS (64 bit)" %}

```
curl -sSLf "$(curl -sSLf https://api.github.com/repos/tomwright/dasel/releases/latest | grep browser_download_url | grep -v .gz | grep darwin_amd64 | cut -d\" -f 4)" -L -o dasel && chmod +x dasel
mv ./dasel /usr/local/bin/dasel
```

{% endtab %}

{% tab title="Windows" %}

```powershell
$releases = Invoke-RestMethod -Uri https://api.github.com/repos/tomwright/dasel/releases/latest
Invoke-WebRequest -Uri ($releases.assets `
                    | Where-Object { $_.name -eq "dasel_windows_amd64.exe" } `
                    | Select-Object -ExpandProperty browser_download_url) `
                    -OutFile dasel.exe
```

{% endtab %}
{% endtabs %}

## Scoop

Use the scoop command-line installer to install dasel on windows 10.

```shell
scoop bucket add extras
scoop install dasel
```

## Development Version

You can `go install` the `cmd/dasel` package to build and install dasel for you.

{% hint style="info" %}
You may need to prefix the command with `GO111MODULE=on` in order for this to work.
{% endhint %}

```
go install github.com/tomwright/dasel/v3/cmd/dasel@master
```


# Shell Completion

Dasel can generate shell completion scripts for **Bash**, **Zsh**, **Fish**, and **PowerShell**. These scripts provide tab-completion for subcommands, flags, and supported data formats.

## Bash

```shell
# Add to ~/.bashrc
source <(dasel completion bash)
```

Or save to a file:

```shell
dasel completion bash > /etc/bash_completion.d/dasel
```

## Zsh

```shell
# Add to ~/.zshrc
source <(dasel completion zsh)
```

Or save to a file:

```shell
dasel completion zsh > "${fpath[1]}/_dasel"
```

{% hint style="info" %}
You may need to run `compinit` after adding the completion script for the first time.
{% endhint %}

## Fish

```shell
dasel completion fish | source
```

Or save to a file:

```shell
dasel completion fish > ~/.config/fish/completions/dasel.fish
```

## PowerShell

```powershell
# Add to your PowerShell profile
dasel completion powershell | Out-String | Invoke-Expression
```

Or save to a file:

```powershell
dasel completion powershell > dasel.ps1
# Then source it in your profile
. ./dasel.ps1
```

## What Gets Completed

The completion scripts provide tab-completion for:

* Subcommands (`query`, `version`, `completion`, `man`, etc.)
* Flags (`--in`, `--out`, `--compact`, `--root`, etc.)
* Data formats when using `--in` or `--out` (e.g. `json`, `yaml`, `toml`, `csv`, `xml`)
* Shell names when using `dasel completion`


# Man Page

Dasel can generate its own man page, which can be viewed directly or installed on your system.

## Viewing

To view the man page directly:

```shell
dasel man | man -l -
```

## Installing

To install the man page so it can be accessed with `man dasel`:

```shell
dasel man > /usr/local/share/man/man1/dasel.1
man dasel
```

{% hint style="info" %}
You may need to run the install command with `sudo` depending on your system.
{% endhint %}

## Contents

The generated man page includes:

* A synopsis of the command-line usage
* Descriptions of all subcommands
* All available flags and options for each command
* Usage examples


# Usage from Go

## Introduction

The dasel CLI is a thin wrapper around dasel's Go API. Your application can use the same API to query, transform, and modify structured data.

## Installation

```bash
go get github.com/tomwright/dasel/v3
```

## External API

Dasel exposes three main functions in the root `dasel` package:

* `Select` - Query data and receive results as native Go types (`any`).
* `Query` - Query data and receive results as `*model.Value` types (preserves ordering and metadata).
* `Modify` - Run a query that modifies the given data in-place.

All three accept variadic `execution.ExecuteOptionFn` options for features like variables.

### Parsing formats

You must import any format parsers you need. The parsers register themselves via `init()`:

```go
import (
    _ "github.com/tomwright/dasel/v3/parsing/json"
    _ "github.com/tomwright/dasel/v3/parsing/yaml"
    _ "github.com/tomwright/dasel/v3/parsing/toml"
    _ "github.com/tomwright/dasel/v3/parsing/xml"
    _ "github.com/tomwright/dasel/v3/parsing/csv"
    _ "github.com/tomwright/dasel/v3/parsing/ini"
    _ "github.com/tomwright/dasel/v3/parsing/hcl"
)
```

Only import the formats you actually use.

## Examples

Up to date examples are maintained within the GitHub repository under [api\_example\_test.go](https://github.com/TomWright/dasel/blob/master/api_example_test.go).

### Select: query with native Go types

Use `Select` when you want results as plain Go values (`string`, `int`, `map[string]any`, etc).

```go
package main

import (
    "context"
    "fmt"

    "github.com/tomwright/dasel/v3"
)

func main() {
    myData := map[string]any{
        "users": []map[string]any{
            {"name": "Alice", "age": 30},
            {"name": "Bob", "age": 25},
            {"name": "Tom", "age": 40},
        },
    }

    result, count, err := dasel.Select(
        context.Background(),
        myData,
        `users.filter(age > 27).map(name)...`,
    )
    if err != nil {
        panic(err)
    }

    fmt.Printf("Found %d results:\n", count)
    for _, r := range result.([]any) {
        fmt.Println(r)
    }

    // Output:
    // Found 2 results:
    // Alice
    // Tom
}
```

### Query: query with model.Value types

Use `Query` when you need to preserve key ordering or access metadata.

```go
package main

import (
    "context"
    "fmt"

    "github.com/tomwright/dasel/v3"
)

func main() {
    myData := map[string]any{
        "name": "Tom",
        "age":  30,
    }

    results, count, err := dasel.Query(
        context.Background(),
        myData,
        `name`,
    )
    if err != nil {
        panic(err)
    }

    fmt.Printf("Found %d results\n", count)
    for _, v := range results {
        str, _ := v.StringValue()
        fmt.Println(str)
    }

    // Output:
    // Found 1 results
    // Tom
}
```

### Modify: update data in-place

Use `Modify` to change values within an existing data structure. The data must be passed as a pointer.

```go
package main

import (
    "context"
    "fmt"

    "github.com/tomwright/dasel/v3"
)

func main() {
    myData := map[string]any{
        "user": map[string]any{
            "name": "Tom",
            "age":  30,
        },
    }

    _, err := dasel.Modify(
        context.Background(),
        &myData,
        `user.name`,
        "Jim",
    )
    if err != nil {
        panic(err)
    }

    fmt.Println(myData["user"].(map[string]any)["name"])

    // Output:
    // Jim
}
```

### Reading and writing structured data (format conversion)

Use parsers to read bytes in one format and write them in another.

```go
package main

import (
    "fmt"

    "github.com/tomwright/dasel/v3/parsing"
    _ "github.com/tomwright/dasel/v3/parsing/json"
    _ "github.com/tomwright/dasel/v3/parsing/yaml"
)

func main() {
    jsonInput := []byte(`{"name": "Tom", "age": 30}`)

    // Read JSON
    reader, _ := parsing.Format("json").NewReader(parsing.DefaultReaderOptions())
    value, err := reader.Read(jsonInput)
    if err != nil {
        panic(err)
    }

    // Write YAML
    writer, _ := parsing.Format("yaml").NewWriter(parsing.DefaultWriterOptions())
    yamlOutput, err := writer.Write(value)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(yamlOutput))

    // Output:
    // name: Tom
    // age: 30
}
```

### Compact output

Set `Compact: true` in writer options to produce compact output with no indentation.

```go
opts := parsing.DefaultWriterOptions()
opts.Compact = true
writer, _ := parsing.Format("json").NewWriter(opts)

output, _ := writer.Write(value)
// {"name":"Tom","age":30}
```

### Using variables

Pass variables into queries using `execution.WithVariable`:

```go
package main

import (
    "context"
    "fmt"

    "github.com/tomwright/dasel/v3"
    "github.com/tomwright/dasel/v3/execution"
)

func main() {
    myData := map[string]any{
        "users": []map[string]any{
            {"name": "Alice", "age": 30},
            {"name": "Bob", "age": 25},
        },
    }

    result, _, err := dasel.Select(
        context.Background(),
        myData,
        `users.filter(age > $minAge).map(name)...`,
        execution.WithVariable("minAge", 27),
    )
    if err != nil {
        panic(err)
    }

    for _, r := range result.([]any) {
        fmt.Println(r)
    }

    // Output:
    // Alice
}
```

### Building model.Value manually

You can construct `model.Value` instances directly without parsing from bytes:

```go
import "github.com/tomwright/dasel/v3/model"

// From a Go value
value := model.NewValue(map[string]any{"key": "value"})

// Typed constructors
strVal := model.NewStringValue("hello")
intVal := model.NewIntValue(42)
mapVal := model.NewMapValue()
_ = mapVal.SetMapKey("key", model.NewStringValue("value"))

// Convert back to Go types
goVal, err := value.GoValue()
```

## Project structure

Dasel has the following main packages:

* [dasel](https://github.com/TomWright/dasel/blob/master) - The external API (`Select`, `Query`, `Modify`).
* [model](https://github.com/TomWright/dasel/tree/master/model) - A wrapper around reflection types. This is what dasel uses to access and modify data internally.
* [parsing](https://github.com/TomWright/dasel/tree/master/parsing) - Parsing implementations for each supported format. Each subdirectory contains a reader and writer.
* [execution](https://github.com/TomWright/dasel/tree/master/execution) - The implementation of all dasel features (functions, operators, etc).
* [selector](https://github.com/TomWright/dasel/tree/master/selector) - Parses dasel query strings and returns an AST used by the `execution` package.


# Query syntax

## Overview

Dasel queries are composed of one or more **statements**. Each statement describes how to navigate or transform the data, and the **final statement determines the output value**.

A statement is made up of a sequence of **accessors** or **function calls**, chained together with a dot (`.`) and terminated with a semi-colon (`;`).

* **Accessors** let you step into nested structures (e.g. objects, arrays, maps).
* **Functions** apply transformations or filters to the current value.

### Example

Suppose you have the following JSON document:

```json
{
  "users": [
    {
      "id": 1,
      "name": "Alice",
      "active": true
    },
    {
      "id": 2,
      "name": "Bob",
      "active": false
    }
  ]
}
```

A dasel query might look like this:

```
$activeUsers = $root.users.filter(active == true);
$activeUsers.map(name)
```

* **`$activeUsers =`** \
  Variable assignment.
* **`$root`** \
  Access the root document.
* **`users`**\
  Access the `users` field.
* **`filter(active == true)`**\
  Filter the `users` list to only include elements where `active` is `true`.
* **`;`** \
  Terminate the statement.
* **`$activeUsers`** \
  Access the active users variable we just created.
* **`map`** \
  Iterate through each active user, returning the specified value, in this case `name` .\
  *(Since this is the last statement, this is also the **output value**.)*

Output:

```json
[
  "Alice"
]
```

This query could be written in a more compact form, or split into multiple statements for clarity.\
The following examples are equivalent and will all produce the same result:

```
$root.users.filter(active == true).map(name)
```

```
$activeUsers = $root.users.filter(active == true);
$activeUsers.map(name)
```

```
$activeUsers = $root.users.filter(active == true);
$names = $activeUsers.map(name);
$names
```


# Whitespace

Whitespace is no longer a factor when parsing selectors. The following examples will all do the same thing.

This is really expected, however since this wasn't the case in previous versions I am specifically calling it out.

## With whitespace

```
[
  1,
  2,
  3
].map(
  if ( $this >= 1 ) {
    $this / 1
  } else {
    $this
  }
)
```

## Without whitespace

```
[1,2,3].map(if($this>=1){$this/1}else{$this})
```


# Comments

You can add comments to your queries with the double forward slash `//`.

Everything from the start of a comment until the end of the line will be ignored by dasel.

## Example

```
dasel -o json '
{ // Start of input object creation
  "foo": "bar", // The base "foo" value.
  "name": "Tom" // The original name
} // End of the input object
.
{ // Start of object re-creation
    "baz": foo, // Rename foo to bar
    name // Shorthand for "name": name
} // End of object re-creation'
{
    "baz": "bar",
    "name": "Tom"
}
```


# Types/Literals

Dasel supports the following literal types in queries.

## Integers

Integers are represented as whole numbers.

```
1
5234
-530
```

Note: If `-530` is detected as a bad binary expression (nothing subtract 530) it can be grouped, e.g. `(-530)`.

## Floats

Numbers are interpreted as floats when they contain a decimal place `.` or are followed with an `f`.

```
1.1
23.45
123f
```

## Booleans

Bools are matched by a case insensitive match on `true` or `false`.

```
true
True
TRUE
false
False
FALSE
```

## Strings

Strings are a sequence of characters surrounded by quotes — both single and double quotes are supported.

```
"I am a string"
'I am a string'
"I am a string with an escaped \" inside of me"
```

## Null

The `null` literal represents an absent or empty value.

```
null
```

`null` is returned by functions like [`first`](/functions/first) and [`last`](/functions/last) on empty arrays, and is the fallback trigger for the [`??` coalesce operator](/syntax/coalesce).

## Arrays

Array literals are defined with square brackets. See [Arrays/slices](/syntax/arrays-slices) for full documentation.

```
[1, 2, 3]
["a", "b", "c"]
[1, "mixed", true, null]
```

## Objects

Object/map literals are defined with curly braces. See [Objects/maps](/syntax/objects-maps) for full documentation.

```
{"name": "Tom", "age": 30}
```


# Recursive Descent

The **recursive descent operator** (`..`) allows you to search deeply through the entire document tree, starting at the current node, and return all matching keys, indices, or values.

This operator is most commonly used to extract values from **nested objects** and **arrays** without knowing their exact path.

***

### Syntax

```
..KEY
```

Return an array of all values of the given `KEY`, recursively.

```
..[INDEX]
```

Returns an array of the element at `INDEX` for every array found, recursively.

```
..*
```

Returns an array of **all values** (map values, array elements, scalars) at any depth.

***

### Behaviour

* `..` performs a depth-first traversal of the current node.
* For objects/maps:
  * `..KEY` finds all values where the key is `KEY`.
  * `..*` finds all values (for all keys).
* For arrays:
  * `..[INDEX]` selects the element at `INDEX` from every array found.
  * `..*` selects every element from every array found.
* Scalars (strings, numbers, booleans, nulls) are included when using `..*`.

***

### Examples

#### Example Input

```json
{
  "user": {
    "name": "Alice",
    "roles": ["admin", "editor"],
    "meta": {
      "active": true,
      "score": 42
    }
  },
  "tags": ["x", "y"],
  "count": 10
}
```

***

#### 1. Recursive Key Search

Get all values with the key `name`:

```bash
'..name'
```

Output:

```json
["Alice"]
```

***

#### 2. Recursive Array Index Search

Get the **first element** (`[0]`) of every array:

```bash
'..[0]'
```

Output:

```json
["admin", "x"]
```

***

#### 3. Recursive Wildcard (`..*`)

Get **all values at any depth**:

```bash
'..*'
```

Output:

```json
[
  "Alice",
  "admin",
  "editor",
  true,
  42,
  "x",
  "y",
  10
]
```

***

### The `$key` variable

During recursive descent, the `$key` variable is set to the current map key (string) or array index (int) at each level of traversal. This is available when using `search` predicates in combination with recursive descent.

***

### Notes

* `..` is shorthand for recursive search by key or index.
* For more complex filtering (e.g. values where a key exists, or by type), use the [`search` ](/functions/search)operator.
* The `..` operator is widely known as the **recursive descent operator**, and is similar to:
  * `//` in XPath
  * `..` in JSONPath and yq
  * `..` in jq


# Regex

Regex pattern are represented as unquoted strings, in the format of `r/my regex pattern/`.

Regex patterns can be used with the like `=~` and not like `!~` comparators.

## Limitations

1. Usage is limited to pattern matching for now. Value extraction will come in the future.
2. Patterns must start with `r/` and end with `/`.

## Examples

### Filter for strings starting with `b`

```
["foo", "bar", "baz"].filter($this =~ r/^b/)
[
    "bar",
    "baz"
]

```


# String concatenation

To concatenate strings, simply use the `+` operator.

To concatenate non-string values into string values, use the [toString](/functions/tostring) function.

## Examples

```
"hello" + " " + "world" // "hello world"
"i am " + toString(100) + " years old" // "i am 100 years old"
```


# Arrays/slices

A slice/array is a sequence of elements. They are zero indexed, not a fixed size and can be modified on the fly.

## Defining a new array

```
[1, 2, 3]
```

## Appending elements to an array

```
[$someArray..., 4]
```

## Removing elements from an array

```
[1, 2, 3].filter($this % 2 == 0)
```

## Accessing by index

```
$someArray[1]
```

Accessing last array index

```
$someArray[len($someArray)-1]
```

## Accessing a range of items

The range index syntax can be a powerful tool: `[start:end]`

The result will be a new array containing the given range of indexes from start to end.

### Take the first 5 items of an array

```
$someArray[0:4]
```

### Take the last 5 items of an array

```
$someArray[ len($someArray)-6 : len($someArray)-1 ]
```


# Objects/maps

An object/map is a set of key value properties.

## Defining a new map

```
{"greeting": "hello"}
```

## Creating a map using existing values

```
{"foo": "bar", "name": "Tom"}. // Just so you can see the input
{
    "baz": foo,
    name // Shorthand for "name": name
}
```

## Adding new fields to a map

We can utilise the spread `...` operator here.

Set `"name" = "Tom"` regardless of what is in the map already:

```
{
  $this...,
  "name": "Tom"
}
```

Set `"name" = "Tom"` only if it doesn't already exist in the map:

```
{
    "name": "Tom",
    $this...
}
```


# Operators

Dasel supports a range of operators for arithmetic, comparison, logic, assignment, and pattern matching.

## Arithmetic Operators

Arithmetic operators work on numeric values (`int` and `float`). If either operand is a float, the result is a float.

| Operator | Description    | Example  | Result |
| -------- | -------------- | -------- | ------ |
| `+`      | Addition       | `3 + 2`  | `5`    |
| `-`      | Subtraction    | `10 - 4` | `6`    |
| `*`      | Multiplication | `3 * 4`  | `12`   |
| `/`      | Division       | `10 / 3` | `3`    |
| `%`      | Modulo         | `10 % 3` | `1`    |

The `+` operator also works for [string concatenation](/syntax/string-concatenation).

#### Examples

```
5 + 3    // 8
10 - 4   // 6
3 * 4    // 12
10 / 3   // 3 (integer division)
10 / 3.0 // 3.333... (float division)
10 % 3   // 1
```

## Comparison Operators

Comparison operators return a boolean value.

| Operator | Description               | Example          | Result |
| -------- | ------------------------- | ---------------- | ------ |
| `==`     | Equal                     | `1 == 1`         | `true` |
| `!=`     | Not equal                 | `1 != 2`         | `true` |
| `>`      | Greater than              | `3 > 2`          | `true` |
| `>=`     | Greater than or equal     | `3 >= 3`         | `true` |
| `<`      | Less than                 | `2 < 3`          | `true` |
| `<=`     | Less than or equal        | `3 <= 3`         | `true` |
| `=~`     | Like (regex match)        | `"foo" =~ r/^f/` | `true` |
| `!~`     | Not like (regex no match) | `"foo" !~ r/^b/` | `true` |

#### Examples

```
"hello" == "hello" // true
"hello" != "world" // true
5 > 3              // true
5 >= 5             // true
2 < 3              // true
3 <= 3             // true
"bar" =~ r/^b/     // true
"bar" !~ r/^f/     // true
```

See [Regex](/syntax/regex) for more on pattern matching.

## Logical Operators

Logical operators combine boolean expressions.

| Operator | Description | Example           | Result  |
| -------- | ----------- | ----------------- | ------- |
| `&&`     | And         | `true && false`   | `false` |
| `\|\|`   | Or          | `true \|\| false` | `true`  |

#### Examples

```
age > 18 && age < 65   // true if age is between 18 and 65
name == "Tom" || name == "Jim"  // true if name is either
```

## Assignment Operator

The `=` operator assigns a value. It can be used to set variables, modify fields, or update array elements.

| Operator | Description | Example           |
| -------- | ----------- | ----------------- |
| `=`      | Assign      | `foo.bar = "new"` |

#### Examples

**Set a variable**

```
$name = "Tom";
$name
// "Tom"
```

**Modify a field**

```bash
$ echo '{"name": "old"}' | dasel -i json --root 'name = "new"'
{
    "name": "new"
}
```

**Modify in a loop**

```bash
$ echo '[1, 2, 3]' | dasel -i json 'each($this = $this + 10)'
[11, 12, 13]
```

See [Modifying data](/input-output/modifying-data) for more details.

## Coalesce Operator

The `??` operator provides a fallback value when the left side is `null`, missing, or errors.

| Operator | Description | Example                |
| -------- | ----------- | ---------------------- |
| `??`     | Coalesce    | `foo.bar ?? "default"` |

See [Coalesce](/syntax/coalesce) for full documentation.

## Spread Operator

The `...` operator unpacks arrays or maps into their individual elements.

| Operator | Description | Example                   |
| -------- | ----------- | ------------------------- |
| `...`    | Spread      | `[1, 2, 3].sum($this...)` |

See [Spread](/syntax/spread) for full documentation.


# Conditionals

Conditionals allow you to select different values depending on an expression. Dasel v3 supports an `if/elseif/else` block syntax and a ternary operator (`?:`).

***

### Syntax

```
if (<condition>) { <then> } else { <else> }
```

* `<condition>` must evaluate to a boolean.
* `<then>` is evaluated if the condition is true.
* `<else>` is evaluated if the condition is false.
* An `else` branch is always required.

***

### Basic Example

**Input JSON**

```json
{
  "foo": {
    "bar": "baz",
    "bong": "selected",
    "qux": "not-selected"
  }
}
```

**Query**

```bash
echo '{"foo":{"bar":"baz","bong":"selected","qux":"not-selected"}}' | dasel -i json 'foo.if (bar == "baz") { bong } else { qux }'
```

**Output**

```
"selected"
```

***

### Elseif Chains

Use `elseif` to chain multiple conditions. You can use as many `elseif` branches as needed.

```
if (<condition1>) { <result1> } elseif (<condition2>) { <result2> } else { <default> }
```

#### Example

**Input JSON**

```json
{ "score": 75 }
```

**Query**

```bash
echo '{"score": 75}' | dasel -i json '
  if (score >= 90) { "A" }
  elseif (score >= 80) { "B" }
  elseif (score >= 70) { "C" }
  else { "F" }
'
```

**Output**

```
"C"
```

#### Fizzbuzz with elseif

Given `numbers.json`:

```json
{ "numbers": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] }
```

```bash
$ cat numbers.json | dasel -i json 'numbers.map(
    if ($this % 3 == 0 && $this % 5 == 0) {
        "fizzbuzz"
    } elseif ($this % 5 == 0) {
        "buzz"
    } elseif ($this % 3 == 0) {
        "fizz"
    } else {
        $this
    }
)'
```

***

### Literal Results

Both branches can return literal values, not just field lookups.

**Input JSON**

```json
{ "count": 7 }
```

**Query**

```bash
echo '{"count": 7}' | dasel -i json 'if (count > 5) { "many" } else { "few" }'
```

**Output**

```
"many"
```

***

### Nested Conditionals

Conditionals can be nested in the `else` branch.

```bash
echo '{"status": "pending"}' | dasel -i json '
  if (status == "active") { "go" }
  else { if (status == "pending") { "wait" } else { "stop" } }
'
```

For multi-branch cases, `elseif` is cleaner than nesting.

***

## Ternary Operator

The ternary operator provides a compact inline syntax for conditionals.

### Syntax

```
<condition> ? <then> : <else>
```

* `<condition>` must evaluate to a boolean.
* `<then>` is returned when the condition is true.
* `<else>` is returned when the condition is false.

### Example

**Input JSON**

```json
{ "age": 25 }
```

**Query**

```bash
echo '{"age": 25}' | dasel -i json 'age >= 18 ? "adult" : "minor"'
```

**Output**

```
"adult"
```

### Nested Ternary

Parentheses can be used to nest ternary expressions.

```bash
echo '{}' | dasel -i json 'true ? (false ? "a" : "b") : "c"'
```

**Output**

```
"b"
```

***

### Notes

* An `else` branch is always required — both `if/else` and `if/elseif/else` must have a final `else`.
* Both branches must return a value — you cannot have an empty branch.
* Use `elseif` (one word, no space) for chained conditions.
* Parentheses around the condition are required for `if`/`elseif` blocks but not for the ternary operator.
* The ternary operator always requires both `?` and `:` parts.


# Spread

The spread operator `...` can be used to spread the contents of a map or array across function arguments or array/object constructors, depending on the situation.

Anothor primary use-case is to output results as separate documents when put at the end of the output statement.

## Examples

```
doSomething([1, 2, 3]...)
// equivalent to doSomething(1, 2, 3)

[[1, 2, 3]..., 4, 5, 6]
// resolves to [1, 2, 3, 4, 5, 6]

{ {"firstName": "Tom"}..., "lastName": "Wright" }
// resolves to { "firstName": "Tom", "lastName": "Wright" }

[1, 2, 3]...
// 1
// 2
// 3
```


# Coalesce

The coalesce `??` operator can be used to provide default values when the given path does not exist, or causes some error.

The operator will pass through to the secondary value if:

* A given map key doesn't exist
* A given array index doesn't exist
* The given expressions returns `null`
* An operation is performed on an invalid type

## Examples

### Check if a property or index exists

```
if ($someArray[10] ?? false) {
    // exists
} else {
    // does not exist
}

if ($someMap.foo ?? false) {
    // exists
} else {
    // does not exist
}
```

### Default values when something doesn't exist

```
foo.bar.baz ?? "my sensible default"
```

### Chaining

The coalesce operator can be chained, with items towards the left taking prescedence.

```
foo ?? bar ?? baz ?? false
```


# Branches

{% hint style="warning" %}
This feature is potentially unstable. Must be used with the `--unstable` flag.
{% endhint %}

Dasel includes the concept of branches. `branch` allows you to perform one or more sub queries, with each query output as a separate document.

***

## Without branching

When we don't branch, the result is an array containing the items.

Given `numbers.json`:

```json
{ "numbers": [{"x": 1}, {"x": 2}, {"x": 3}] }
```

```bash
$ cat numbers.json | dasel -i json 'numbers'
[
    {
        "x": 1
    },
    {
        "x": 2
    },
    {
        "x": 3
    }
]
```

***

## Branching on an array

When we branch, each element is output as a **separate document** instead of a single array.

```bash
$ cat numbers.json | dasel -i json 'branch(numbers...)'
{
    "x": 1
}
{
    "x": 2
}
{
    "x": 3
}
```

***

## Filtering branches with ignore

Since `filter` operates on arrays and a branch isn't technically an array, you can use [`ignore`](/functions/ignore) to exclude specific branches from the result.

```bash
$ echo '[1, 2, 3]' | dasel -i json 'branch().if ($this == 2) { ignore() } else { $this }'
1
3
```

Here, the element `2` is matched by the condition and `ignore()` removes it from the output. The remaining elements `1` and `3` are output as separate documents.

***

## Extracting multiple fields as separate documents

```bash
$ echo '{"name": "Tom", "age": 30, "city": "London"}' \
  | dasel -i json 'branch(name, age)'
"Tom"
30
```

***

## Notes

* `branch` converts an array (or multiple values) into separate output documents.
* Use the [spread operator](/syntax/spread) (`...`) to unpack an array into branch arguments.
* Use [`ignore`](/functions/ignore) to conditionally exclude branches.


# Read/Write formats

Dasel supports a number of file formats out of the box.

| Format | Read                 | Write                | Notes                                                                                                                                                                                                   |
| ------ | -------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| json   | :white\_check\_mark: | :white\_check\_mark: |                                                                                                                                                                                                         |
| yaml   | :white\_check\_mark: | :white\_check\_mark: |                                                                                                                                                                                                         |
| hcl    | :white\_check\_mark: | :white\_check\_mark: | [Flags available.](/input-output/read-writer-flags#hcl)                                                                                                                                                 |
| csv    | :white\_check\_mark: | :white\_check\_mark: | <p><a href="/pages/vs3gpbQfCDqAy6nFm1Qw#csv">Flags available.</a><br>All values read/written as strings.</p>                                                                                            |
| toml   | :grey\_question:     | :grey\_question:     | <p>Generally working.<br>Unsorted maps.</p>                                                                                                                                                             |
| xml    | :white\_check\_mark: | :white\_check\_mark: | <p><a href="/pages/vs3gpbQfCDqAy6nFm1Qw#xml">Flags available.</a><br>Attribute names are prefixed with a <code>-</code> and should be accessed using <a href="/pages/mHhp6NHuJ42wXg2EF9uk">get</a>.</p> |
| ini    | :white\_check\_mark: | :white\_check\_mark: | Limited to basic sections + key values.                                                                                                                                                                 |
| kdl    | :white\_check\_mark: | :white\_check\_mark: | <p><a href="/pages/vs3gpbQfCDqAy6nFm1Qw#kdl">Flags available.</a><br>Supports both v1 and v2 syntax. See <a href="/pages/34XwQcQhhD5gAUSBDait">KDL format</a> for data model details.</p>               |
| dasel  | :white\_check\_mark: | :x:                  | This is not a real format, but instead allows dasel literals to be parsed on input strings.                                                                                                             |
| plain  | :x:                  | :white\_check\_mark: | Writes scalar values as plain strings without any quotes.                                                                                                                                               |


# Stdin

It's common that you will want to pass some input into dasel to work with.

The simplest way of doing so is sending it to `stdin`, e.g.

`echo '{"message": "Hello world"}' | dasel -i json`&#x20;

This data could be in many formats (`json`, `yaml`, etc), so it's important that you use `-i`, `--input` to specify the input file format.

Note that if you provide an input format, you must write to stdin other dasel will hang waiting for input.

## Outputting the root document with --root

By default, dasel outputs the result of the final selector. This is useful when searching for data, but not so useful when performing modifications.

```
$ echo '{
  "foo": {
    "bar": "baz"
  }
}' | dasel -i json 'foo.bar'
"baz"

$ echo '{
  "foo": {
    "bar": "baz"
  }
}' | dasel -i json 'foo.bar = "bong"'
"bong"

$ echo '{
  "foo": {
    "bar": "baz"
  }
}' | dasel -i json --root 'foo.bar = "bong"'
{
    "foo": {
        "bar": "bong"
    }
}

```


# Stdout

Dasel writes to stdout.

You can modify the output with the `-o`, `--out` flag passing the required format, e.g. `json`, `yaml` etc.

```
$ echo '{"message": "Hello world"}' | dasel -i json -o yaml
message: Hello world
```

## Getting the output you want

Dasel will output the result of the final expression by default, however in some cases it can be useful to output the input document, e.g.

### Default behaviour

```
$ echo '{"user": {"name": "John"}}' |
    dasel -i json 'user.name = {"first": user.name, "last": "Doe"}'

// outputs
{"first": "John", "last": "Doe"}
```

### With --root

<pre><code>$ echo '{"user": {"name": "John"}}' |
    dasel -i json --root 'user.name = {"first": user.name, "last": "Doe"}'

// outputs
<strong>{"user": {"name": {"first": "John", "last": "Doe"}}}
</strong></code></pre>

## Compact output

By default, dasel pretty-prints structured output with indentation and newlines. Use the `--compact` flag to produce compact output with no extra whitespace.

This is supported for JSON, TOML, YAML, and XML formats.

```
$ echo '{"name": "Tom", "age": 30}' | dasel -i json -o json --compact
{"name":"Tom","age":30}
```

```
$ echo '<Root><Name>Tom</Name></Root>' | dasel -i xml -o xml --compact
<Root><Name>Tom</Name></Root>
```


# Modifying data

{% hint style="success" %}
Use `--root` whenever you are **modifying data and intend to save it back to a file**.\
This ensures you get the complete updated document rather than just the changed value.
{% endhint %}

### Output Behaviour

By default, **dasel outputs the result of the final selector** in your query.\
This is convenient when you’re simply retrieving a value, but can be less helpful when you’re modifying data, since you often want to see the full document instead.

***

#### Retrieving a Value

```bash
$ echo '{
  "foo": {
    "bar": "baz"
  }
}' | dasel -i json 'foo.bar'
"baz"
```

Here, the final selector is `foo.bar`, so dasel outputs its value: `"baz"`.

***

#### Modifying a Value

```bash
$ echo '{
  "foo": {
    "bar": "baz"
  }
}' | dasel -i json 'foo.bar = "bong"'
"bong"
```

When updating a value, dasel still outputs the result of the final selector — in this case, the new value `"bong"`.

***

#### Outputting the Entire Document

To print the entire modified document, use the `--root` flag.\
This changes the output to always return the full root node, regardless of the final selector.

```bash
$ echo '{
  "foo": {
    "bar": "baz"
  }
}' | dasel -i json --root 'foo.bar = "bong"'
{
  "foo": {
    "bar": "bong"
  }
}
```

***

#### Comparison

| Mode     | Example Command                           | Output                                 |
| -------- | ----------------------------------------- | -------------------------------------- |
| Default  | `dasel -i json 'foo.bar = "bong"'`        | `"bong"` (final selector value)        |
| `--root` | `dasel -i json --root 'foo.bar = "bong"'` | Full document with updated `"foo.bar"` |


# Variables

Dasel allows you to define variables for use in your queries.

Variables are referenced using a `$` prefix.

Note that these variables are essentially globals, and once defined, they are accessible at any point in the execution.

Variables can be used alongside `stdin`.

## Inline

Inline variables are those defined within a dasel query itself and should be terminated with a semicolon.

```bash
$ dasel -i json '$x = 1; $y = 2; $x + $y'
3
```

**Multi-step data transformation**

```bash
$ echo '{"users": [{"name": "Alice"}, {"name": "Bob"}]}' \
  | dasel -i json '
    $names = users.map(name);
    $count = len($names);
    "Found " + toString($count) + " users"
  '
"Found 2 users"
```

## From the environment

You can access environment variables using `$ENV_VAR_NAME`.

Note that changes to environment variables within dasel **are not supported**.

```bash
$ GREETING=hello NAME=tom dasel '$GREETING + " " + $NAME'
"hello tom"
```

## From the CLI

You can set variables from the CLI by passing additional arguments in the form of:

`--var name=format:content`

If you wish to pass a file as a variable you can use:

`--var name=format:file:filepath`

```bash
$ echo 'message: Hello world' > test.yaml
$ dasel -o json testVar=yaml:file:test.yaml '$testVar.message'
"Hello world"
```

Note that at this time variables from the CLI are currently required to be documents read from the file system. There are plans to change this in the future.

## Standard variables

Some variables are provided by dasel and will always exist:

* `$root` - The root document passed through `stdin` or `-f`.

### `$this`

`$this` refers to the **current element** being processed. It is available inside expressions that iterate over arrays:

* [`map`](/functions/map) — `$this` is the current element being transformed.
* [`filter`](/functions/filter) — `$this` is the current element being tested.
* [`each`](/functions/each) — `$this` is the current element being visited.
* [`sortBy`](/functions/sortby) — `$this` is the current element being compared.
* [`any`](/functions/any) / [`all`](/functions/all) / [`count`](/functions/count) — `$this` is the current element being evaluated.

It is also available in [spread](/syntax/spread) contexts and when accessing the current node in conditionals.

#### Examples

```
[1, 2, 3].map($this * 2)
// [2, 4, 6]

[1, 2, 3].filter($this > 1)
// [2, 3]

["hello", "WORLD"].map(toLower($this))
// ["hello", "world"]
```

### `$key`

`$key` refers to the **current index or key** during iteration. For arrays/slices it is an integer index (starting at 0); for maps/objects it is the string key name.

`$key` is available inside all iteration expressions:

* [`map`](/functions/map) / [`filter`](/functions/filter) / [`each`](/functions/each) / [`sortBy`](/functions/sortby) / [`groupBy`](/functions/groupby) — `$key` is the slice index.
* [`any`](/functions/any) / [`all`](/functions/all) / [`count`](/functions/count) / [`reduce`](/functions/reduce) — `$key` is the slice index.
* [`mapValues`](/functions/mapvalues) — `$key` is the map key name (string).
* [`search`](/functions/search) / [recursive descent](/syntax/recursive-descent) — `$key` is the map key (string) or slice index (int) depending on context.

`$key` is scoped to the iteration — it does not leak into outer expressions.

#### Examples

```
[10, 20, 30].map($key)
// [0, 1, 2]

[10, 20, 30].filter($key >= 1)
// [20, 30]

{"a": 1, "b": 2}.mapValues($key)
// {"a": "a", "b": "b"}

[10, 20, 30].map($key + $this)
// [10, 21, 32]
```


# Read/Writer flags

Some parsers accept options that aren't available in others, for this we use read/writer flags.

## Format

```
--read-flag foo=bar
--write-flag foo=bar
```

## Flags by parser

### CSV

| Read/Write | Name          | Values                                                    | Description                                                |
| ---------- | ------------- | --------------------------------------------------------- | ---------------------------------------------------------- |
| read/write | csv-delimiter | Any single character to use as a delimiter. E.g. `,`, `;` | Changes the delimiter used when reading/writing CSV files. |

### XML

| Read/Write | Name     | Values     | Description                                                      |
| ---------- | -------- | ---------- | ---------------------------------------------------------------- |
| read       | xml-mode | structured | Changes the internal structure that XML documents are read into. |

### HCL

| Read/Write | Name             | Values | Description                                                                                                                                                                                                     |
| ---------- | ---------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| read       | hcl-block-format | array  | HCL block contents usually expand to an array when duplicate labels are defined on another block. Setting this to `array` will force blocks to always be an array of values, even when there are no duplicates. |

### KDL

| Read/Write | Name        | Values | Description                                                                                                                            |
| ---------- | ----------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------- |
| write      | kdl-version | 1, 2   | Controls the output KDL version. Version `2` (default) uses `#true`, `#false`, `#null`. Version `1` uses bare `true`, `false`, `null`. |


# KDL format

[KDL](https://kdl.dev/) (KDL Document Language) is a node-oriented document language. Dasel supports both v1 and v2 syntax for reading, and outputs v2 by default.

## Version support

KDL has two versions with slightly different syntax for keywords:

| Feature            | v1                  | v2                    |
| ------------------ | ------------------- | --------------------- |
| Booleans           | `true` `false`      | `#true` `#false`      |
| Null               | `null`              | `#null`               |
| Raw strings        | `r"..."` `r#"..."#` | `#"..."#` `##"..."##` |
| Multi-line strings | Not supported       | `"""..."""`           |
| Special floats     | N/A                 | `#inf` `#-inf` `#nan` |

When reading, dasel auto-detects the version from the syntax used, or from a `/- kdl-version N` marker at the start of the document. Both versions produce the same data model.

When writing, dasel outputs v2 syntax by default. Use `--write-flag kdl-version=1` for v1 output.

## Data model

KDL is node-oriented — each node has a name, optional arguments, optional properties (key=value), and optional children. Dasel maps this to its standard map/slice model:

### Scalar nodes

A node with a single argument, no properties, and no children becomes a direct scalar value:

```kdl
name "Bob"
age 76
active #true
```

```json
{
    "name": "Bob",
    "age": 76,
    "active": true
}
```

### Nodes with properties and children

Properties become map keys. Children are merged in as nested keys. Arguments are stored under a `$args` key:

```kdl
server 80 host="localhost" {
    tls #true
}
```

```json
{
    "server": {
        "$args": [80],
        "host": "localhost",
        "tls": true
    }
}
```

### Duplicate node names

Duplicate node names at the same level are automatically promoted to a slice:

```kdl
plugin "git"
plugin "docker"
plugin "tmux"
```

```json
{
    "plugin": ["git", "docker", "tmux"]
}
```

### Empty nodes

A node with no arguments, properties, or children maps to `null`:

```kdl
marker
```

```json
{
    "marker": null
}
```

## Examples

### Read a value from KDL

```bash
echo 'name "Bob"' | dasel -i kdl 'name'
```

### Convert KDL to JSON

```bash
echo 'name "Bob"
age 76' | dasel -i kdl -o json '$root'
```

### Convert JSON to KDL

```bash
echo '{"name": "Bob", "age": 76}' | dasel -i json -o kdl '$root'
```

### Output as KDL v1

```bash
echo '{"active": true}' | dasel -i json -o kdl --write-flag kdl-version=1 '$root'
# Output: active true
```

### Query nested KDL

```bash
echo 'server {
    host "localhost"
    port 8080
}' | dasel -i kdl 'server.host'
```

### Query duplicate nodes by index

```bash
echo 'plugin "git"
plugin "docker"
plugin "tmux"' | dasel -i kdl 'plugin[1]'
# Output: "docker"
```




---

[Next Page](/llms-full.txt/1)

