ConfigDSL++ is a toolkit for C++ application configuration. It includes:
- Library: Define configuration structure once as C++ code; the library handles parsing and validation.
- CLI Tool (
conf-lint): Validate configuration files and generate documentation.
- Why?
- Installation
- Quick Start
- ConfigDSL++ vs Alternatives
- Key Features
- Build & Test
- CLI Tool (
conf-lint)
Parsing JSON configuration files manually is prone to errors, typos, and crashes. Traditional C++ parsers often crash the application with unhandled exceptions or std::abort when encountering type mismatches or missing fields. For example, if a user types "port": "default" (string) instead of "port": 8080 (number), the application may terminate in production.
Define a schema in C++ code. The library validates JSON against this schema before applying it. On errors (typos, wrong types, missing fields), it returns an aggregated list of errors instead of crashing. The application reports errors and refuses to start unsafe operations.
this library is useful for applications that need to keep running even when the configuration file has errors. Especially for servers that must stay online, embedded devices that are hard to restart, or any project where config files are edited manually by humans.
Add this to your CMakeLists.txt:
include(FetchContent)
FetchContent_Declare(
configdsl
GIT_REPOSITORY https://github.com/abaj0ur/ConfigDSL.git
GIT_TAG main # or a specific tag like v2.0.0
)
FetchContent_MakeAvailable(configdsl)
target_link_libraries(your_app PRIVATE configdsl::lib)- Download the latest Release (ZIP file) from this repository.
- Copy the
include/configfolder into your project. - Add
#include <config/config.hpp>. - Note: You also need
nlohmann/jsoninstalled.
- Compiler: C++20 compliant (MSVC 19.29+, GCC 10+, Clang 10+).
- Build System: CMake 3.25+.
- Dependencies:
nlohmann/json,fmt,tl-expected(Managed via vcpkg).
#include <config/config.hpp>
struct ServerConfig {
std::string host;
int port;
std::vector<int> blocked_ports; // Supports STL containers
// The Schema IS the code
static constexpr auto schema() {
return std::make_tuple(
config::field("host", &ServerConfig::host).fallback("localhost"),
config::field("port", &ServerConfig::port)
// β
Validators must be noexcept
.validate(+[](const int& p) noexcept { return p > 0 && p < 65535; }),
config::field("blocked_ids", &ServerConfig::blocked_ports)
);
}
};int main() {
// Input JSON (e.g., from file)
nlohmann::json j = R"({
"host": "production-db",
"port": 99999,
"blocked_ids": ["NaN", 22]
})"_json;
ServerConfig cfg;
auto result = config::parse_json(cfg, j);
if (!result) {
// Errors are aggregated (Fail-Soft), not thrown
for (const auto& err : result.error()) {
std::cerr << "β " << err.path << ": " << err.message << "\n";
}
}
}β port: Validation failed (value 99999)
β blocked_ids[0]: Type mismatch: expected integer
There are many JSON libraries. Here is where ConfigDSL++ fits:
| Feature | ConfigDSL++ | nlohmann/json | Protobuf / Cap'n Proto |
|---|---|---|---|
| Primary Goal | Safety & Validation | Ease of Use | Serialization Speed |
| Type Safety | β Compile-Time | β None (Runtime) | β Strong |
| Schema Def. | β Native C++ Struct | β None | .proto files |
| Error Handling | β Aggregated List | ||
| Integration | β Header-Only | β Header-Only | β Requires Compiler/Codegen |
Key Differentiator: Unlike reflection libraries (like Glaze or Reflect-cpp) which rely on implicit memory layout, ConfigDSL++ uses an Explicit Schema. This means reordering fields in your struct will not break compatibility with existing config files.
- Crash-Free: Uses a "Fail-Soft" approach. Bad input leads to error messages, not program termination.
- Type Safety: Integers are checked for overflows. Strings are checked for correctness.
- Strict Mode: Detects typos! If your JSON has a field
"prt"instead of"port", the library will warn you (unlike standard parsers which silently ignore it). - Auto-Documentation: Since the schema is in the code, the library can generate a Markdown table explaining your config options automatically.
We use CMake Presets for reproducible builds. Choose your platform:
# 1. Configure
cmake --preset unix-debug
# 2. Build Library & Tools
cmake --build --preset unix-debug
# 3. Run Unit Tests
ctest --preset unix-debug# 1. Configure
cmake --preset windows-debug
# 2. Build Library & Tools
cmake --build --preset windows-debug
# 3. Run Unit Tests
ctest --preset windows-debugThis project includes a CLI tool that validates configuration files and generates documentation, e.g., in CI context.
After building (see Build & Test), you can run it directly.
Validate a file:
# Linux / macOS
./build/src/conf-lint --check config.json
# Windows (if built with windows-debug preset)
.\out\build\windows-debug\src\conf-lint.exe --check demo_data\demo_valid.jsonGenerate Documentation:
# Linux / macOS
./build/src/conf-lint --gen-doc > CONFIG_DOCS.md
# Windows
.\out\build\windows-debug\src\conf-lint.exe --gen-doc > CONFIG_DOCS.md# Configuration Reference
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `name` | String | "MyService" | App Name |
| `port` | Integer | **Required** | Listening port |
| `logging.level` | String | "INFO" | Log level |
| `logging.verbose` | Boolean | false | Enable verbose output |
| `logging.path` | String | "/var/log/app.log" | Path to log file |
| `security.ssl` | Boolean | true | Require SSL |
| `security.auth_retries` | Integer | 3 | Max login attempts |
| `security.blocked_ports` | Array<Integer> | **Required** | Blacklisted ports (Array) |