# Xray-core Configuration Format: How to Convert Between JSON, Protobuf, and TOML

> Master Xray-core configuration. Learn to effortlessly convert between JSON, Protobuf, and TOML formats using built-in commands for seamless file management.

- Repository: [Project X Community, Not Porn-jet X Hub/Xray-core](https://github.com/XTLS/Xray-core)
- Tags: how-to-guide
- Published: 2026-04-21

---

**Xray-core supports JSON, YAML, TOML, and protobuf configuration formats, with built-in `convert` commands to transform between them losslessly via the internal protobuf representation.**

The Xray-core proxy framework accepts multiple human-readable configuration formats, all of which resolve to the same internal protobuf structures. This guide explains the configuration architecture, demonstrates format conversion using the official CLI tools, and provides working examples based on the XTLS/Xray-core source code.

## How Xray-core Handles Configuration Formats

Xray-core defines a `ConfigFormat` struct in [`core/config.go`](https://github.com/XTLS/Xray-core/blob/main/core/config.go) that pairs file extensions with loader functions. The registration system allows each format to implement its own parsing logic while converging on identical protobuf output.

### The ConfigFormat Architecture

```go
// core/config.go – ConfigFormat definition
type ConfigFormat struct {
    Name      string
    Extension []string
    Loader    ConfigLoader
}

```

The `RegisterConfigLoader` function in the same file populates a global map (`configLoaderByExt`) that `GetFormatByExtension` queries at runtime:

```go
// core/config.go – extension to format resolution
func GetFormatByExtension(ext string) string {
    switch strings.ToLower(ext) {
    case "pb", "protobuf": return "protobuf"
    case "yaml", "yml":    return "yaml"
    case "toml":           return "toml"
    case "json", "jsonc":  return "json"
    default:               return ""
    }
}

```

### Format-Specific Loader Implementations

| Format | Extensions | Source File | Implementation |
|--------|-----------|-------------|----------------|
| **JSON / JSONC** | `json`, `jsonc` | [`main/main/json/json.go`](https://github.com/XTLS/Xray-core/blob/main/main/main/json/json.go) | Uses `jsonpb` for protobuf conversion |
| **YAML** | `yaml`, `yml` | [`main/main/yaml/yaml.go`](https://github.com/XTLS/Xray-core/blob/main/main/main/yaml/yaml.go) | Parses to map, then to protobuf |
| **TOML** | `toml` | [`main/main/toml/toml.go`](https://github.com/XTLS/Xray-core/blob/main/main/main/toml/toml.go) | Uses `github.com/pelletier/go-toml` |
| **Protobuf** | `pb`, `protobuf` | Internal | Binary serialized format |

The TOML loader in [`main/main/toml/toml.go`](https://github.com/XTLS/Xray-core/blob/main/main/main/toml/toml.go) specifically uses the third-party `go-toml` library to transform TOML structures into intermediate maps before protobuf conversion, as seen in [`infra/conf/serial/loader.go`](https://github.com/XTLS/Xray-core/blob/main/infra/conf/serial/loader.go).

## Converting Between Xray-core Configuration Formats

Xray-core includes a `convert` command suite in `main/main/commands/all/convert/` for bidirectional transformation. All conversions pass through the internal protobuf representation, ensuring no data loss.

### JSON to Protobuf Conversion

The `convert pb` command merges multiple JSON files and outputs a binary protobuf file:

```bash

# Merge two JSON fragments into a single protobuf file

xray convert pb -outpbfile config.pb config1.json config2.json

```

This command delegates to `ConfigMergedFormFiles` in [`core/config.go`](https://github.com/XTLS/Xray-core/blob/main/core/config.go), which loads each JSON file through its registered loader, merges the resulting protobuf structures, and serializes the final config to binary format.

**Example input files:**

```json
// config1.json
{
  "log": { "level": "info" }
}

```

```json
// config2.json
{
  "policy": { "system": "auto" }
}

```

### Protobuf to JSON Conversion

The `convert json` command reverses the process, reading a binary protobuf file and producing human-readable JSON:

```bash

# Convert protobuf back to JSON

xray convert json -type Config config.pb

```

The `-type` flag specifies the root protobuf message type (typically `Config`). The source in [`main/main/commands/all/convert/json.go`](https://github.com/XTLS/Xray-core/blob/main/main/main/commands/all/convert/json.go) uses `jsonpb` marshaling to produce pretty-printed output suitable for editing or version control.

### TOML Configuration Direct Usage

Xray-core can load TOML directly without explicit conversion:

```toml

# myconfig.toml

[log]
  level = "warning"

[policy]
  system = "auto"

```

```bash

# Run Xray with TOML config

xray run -c myconfig.toml

```

The `run` command calls `GetFormat("myconfig.toml")`, resolves the `toml` format, and invokes the loader from [`main/main/toml/toml.go`](https://github.com/XTLS/Xray-core/blob/main/main/main/toml/toml.go) to transform the TOML into the internal protobuf `Config` object.

## Why Protobuf Is the Canonical Format

All Xray configuration objects originate from protobuf definitions in `*.proto` files distributed throughout the repository. For example, VMess outbound configuration uses `proxy/vmess/outbound/config.proto`.

This design makes the conversion pipeline inherently consistent:

```

JSON/YAML/TOML → loader → internal protobuf Config → (optional) serialize → .pb file

```

The `convert` commands simply expose this internal pipeline as CLI operations. Because all formats resolve to the same protobuf structs, converting between them is lossless and idempotent.

## Summary

- **Xray-core configuration** supports JSON, JSONC, YAML, TOML, and binary protobuf formats through a unified `ConfigFormat` registration system in [`core/config.go`](https://github.com/XTLS/Xray-core/blob/main/core/config.go)
- **Format loaders** in [`main/main/json/json.go`](https://github.com/XTLS/Xray-core/blob/main/main/main/json/json.go), [`main/main/yaml/yaml.go`](https://github.com/XTLS/Xray-core/blob/main/main/main/yaml/yaml.go), and [`main/main/toml/toml.go`](https://github.com/XTLS/Xray-core/blob/main/main/main/toml/toml.go) parse human-readable formats into internal protobuf structures
- **Conversion commands** `xray convert pb` and `xray convert json` in `main/main/commands/all/convert/` provide bidirectional transformation with no data loss
- **Protobuf is the canonical representation** — all formats derive from `.proto` schema definitions, making conversions reliable and consistent

## Frequently Asked Questions

### Does Xray-core support TOML configuration natively?

Yes. Xray-core registers a TOML loader in [`main/main/toml/toml.go`](https://github.com/XTLS/Xray-core/blob/main/main/main/toml/toml.go) that uses the `github.com/pelletier/go-toml` library. You can start Xray with `xray run -c config.toml` without any manual conversion. The loader transforms TOML into the same internal protobuf representation used by JSON and YAML.

### How do I convert multiple JSON configuration files into a single binary file?

Use the `convert pb` command with multiple input files: `xray convert pb -outpbfile merged.pb config1.json config2.json`. The command loads each file through its registered format loader, merges the resulting protobuf structures, and outputs a single serialized binary file. This is useful for distributing compact, tamper-evident configurations.

### Why would I use protobuf format instead of JSON?

The protobuf format (`*.pb`) provides smaller file sizes, faster parsing, and deterministic serialization. Since all Xray configurations ultimately resolve to protobuf according to the schema definitions in `proxy/*/config.proto` and related files, the binary format eliminates any ambiguity from textual parsing. Use `xray convert json -type Config file.pb` to recover human-readable JSON when editing is needed.

### Where are the configuration format loaders registered at runtime?

Format loaders register during program initialization through calls to `core.RegisterConfigLoader` in each format's package. The JSON loader registers in [`main/main/json/json.go`](https://github.com/XTLS/Xray-core/blob/main/main/main/json/json.go), YAML in [`main/main/yaml/yaml.go`](https://github.com/XTLS/Xray-core/blob/main/main/main/yaml/yaml.go), and TOML in [`main/main/toml/toml.go`](https://github.com/XTLS/Xray-core/blob/main/main/main/toml/toml.go). The registration system lives in [`core/config.go`](https://github.com/XTLS/Xray-core/blob/main/core/config.go), which maintains the `configLoaderByExt` map used by `GetFormatByExtension` to resolve file paths to appropriate parsers.