Config
MagicUtils config maps files to POJOs using annotations while preserving user comments and unknown keys when saving.
Why a config manager
Loading a config by hand usually means picking a parser, reading keys one by one, coercing types, filling in defaults for missing keys, and re-serialising without clobbering the comments the user wrote. Do that across JSON, YAML, and TOML and you have three code paths.
MagicUtils turns a config into a plain Java class: annotate the fields, register the class, and you get typed access with defaults, comments, validation, and migrations. The same model loads from JSON, JSONC, YAML, or TOML, and saving preserves user comments and any keys you did not map.
Before (manual, one format, defaults inline everywhere):
After (typed model, defaults and bounds on the field, any format):
Define A Config
If your config path contains placeholders such as {lang} or {service}, pass
them during registration:
Formats And Selection
- JSON / JSONC are available out of the box.
- YAML requires
magicutils-config-yaml. - TOML requires
magicutils-config-toml.
If you use {ext} in @ConfigFile, MagicUtils chooses the extension from the
current config format rules:
<config>.formatnext to the configmagicutils.formatin the root config directory-Dmagicutils.config.format=jsoncMAGICUTILS_CONFIG_FORMAT
Fabric defaults to JSONC when no explicit format is selected.
For advanced format selection and migrations, see Config Advanced.
Reloading And Change Listeners
Register a listener for live updates:
onChange(...) is a lighter variant for when you do not need to unsubscribe: it
registers the same kind of listener but returns nothing instead of a
ListenerSubscription.
@ConfigReloadable restricts which sections can reload at runtime.
Threading Helpers
Reloading touches disk. Use async or smart helpers on blocking-sensitive threads:
Runtime-Managed Config Services
When you already have MagicRuntime, you can bind a config-backed resource and
let MagicUtils rebuild it automatically on matching config reloads:
The bound service is also exposed as a named runtime component.
Migrations
Config migrations are declared with ConfigMigration and tracked by the
config-version key inside the file:
Validation Annotations
@MinValue / @MaxValue
Clamp numeric fields to a safe range. Values outside the range are automatically adjusted when the config is loaded. A warning is logged by default.
Supported types: byte, short, int, long, float, double and their
wrapper types.
Set warn = false to suppress the clamping log message:
@ConfigValue(required = true)
Marks a key as mandatory. If it is missing from the file when the config loads,
MagicUtils throws an IllegalStateException instead of falling back to the field
default:
@DefaultValue
Provides a default string value for a config field when the key is missing from the file:
For dynamic defaults, implement DefaultValueProvider<T> and reference it:
Serializable Types
@ConfigSerializable
Marks a class so it can be used in config lists and maps:
Use includeNulls = true to serialize null fields explicitly.
@SaveTo
Redirects a field to a different file:
The path is relative to the plugin data folder.
@ListProcessor
Applies per-item validation or transformation when loading list fields:
The processor implements ListItemProcessor<T>:
Custom Value Adapters
Register serializers via ConfigAdapters.register(...):
Shutdown
Bootstrap helpers and MagicRuntime can manage the config manager lifecycle
for you. In manual setups, call ConfigManager.shutdown() during plugin or mod
shutdown to stop file watchers cleanly.