cppfig uses a pluggable serialization system. The flat .conf format is the default — zero extra dependencies. JSON, TOML, and other formats are available as opt-in features.
The built-in ConfSerializer uses a simple flat key-value format and requires no additional dependencies:
#include <cppfig/cppfig.h>
// Default — uses .conf serialization
cppfig::Configuration<MySchema> config("config.conf");# Each line is a full dot-path = value
server.host = localhost
server.port = 8080
logging.enabled = true
logging.level = info
- Each line is
full.dot.path = value— what you see is exactly what you write in code. - Lines starting with
#are comments. - No sections, no grouping — one flat list per file.
- Value types are inferred automatically:
true/false/yes/no/on/off→bool- Integer literals →
int64_t - Decimal literals →
double - Everything else →
std::string
- Quoted strings (
"hello world") preserve literal content including spaces.
Enable JSON support by adding the dependency and CMake option:
# Option 1: set the CMake option explicitly
set(CPPFIG_ENABLE_JSON ON)
# Option 2: if nlohmann-json is already available via find_package(),
# it is auto-detected and CPPFIG_ENABLE_JSON is set automatically.
find_package(nlohmann_json CONFIG REQUIRED){
"dependencies": [
{
"name": "cppfig",
"features": ["json"]
}
]
}#include <cppfig/cppfig.h>
#include <cppfig/json.h> // opt-in header
// Explicitly select JsonSerializer as the second template parameter
cppfig::Configuration<MySchema, cppfig::JsonSerializer> config("config.json");{
"server": {
"host": "localhost",
"port": 8080
},
"logging": {
"enabled": true,
"level": "info"
}
}| Format | Header | CMake Option | vcpkg Feature | Status |
|---|---|---|---|---|
| Conf | <cppfig/cppfig.h> |
(always available) | — | Built-in |
| JSON | <cppfig/json.h> |
CPPFIG_ENABLE_JSON |
json |
Available |
| TOML | <cppfig/toml.h> |
CPPFIG_ENABLE_TOML |
toml |
Planned |
| YAML | <cppfig/yaml.h> |
CPPFIG_ENABLE_YAML |
yaml |
Planned |
To create a custom serializer, implement a struct that satisfies the Serializer concept:
#include <cppfig/serializer.h>
struct MyFormatSerializer {
// Required: type alias (must be cppfig::Value)
using data_type = cppfig::Value;
// Required: parse from input stream into a Value tree
static auto Parse(std::istream& is) -> cppfig::StatusOr<cppfig::Value> {
// ... read and convert to cppfig::Value ...
}
// Required: convert a Value tree to a string for saving
static auto Stringify(const cppfig::Value& data) -> std::string {
// ... serialize the Value tree ...
}
};cppfig::Configuration<MySchema, MyFormatSerializer> config("config.myformat");
// Or create a template alias for convenience
template <typename Schema>
using MyFormatConfig = cppfig::Configuration<Schema, MyFormatSerializer>;
MyFormatConfig<MySchema> config("config.myformat");A serializer must provide:
| Member | Signature | Purpose |
|---|---|---|
data_type |
type alias (Value) |
Internal data representation |
Parse |
(std::istream&) → StatusOr<Value> |
Parse from stream |
Stringify |
(const Value&) → std::string |
Convert to string |
Path navigation (GetAtPath, SetAtPath, HasPath) and merging are handled
by cppfig::Value directly — serializers only need to convert between their
file format and a Value tree.
cppfig provides helper functions for file operations:
// Read file into a Value tree via any serializer
auto result = cppfig::ReadFile<cppfig::ConfSerializer>("config.conf");
if (result.ok()) {
cppfig::Value data = *result;
}
// Write a Value tree to a file
cppfig::Status status = cppfig::WriteFile<cppfig::ConfSerializer>(
"config.conf", my_data
);Serializers work with ConfigTraits<T> for type conversion:
// In Configuration::Get<Setting>():
// 1. Get raw value from the Value tree
Value raw = data_.GetAtPath(Setting::path);
// 2. Convert to Setting's value type using ConfigTraits
auto value = ConfigTraits<value_type>::Deserialize(*raw);ConfigTraits<T> works with cppfig::Value (not any specific serializer
format), so custom type traits are serializer-agnostic.