-
Notifications
You must be signed in to change notification settings - Fork 0
Codecs and Formats
A Codec is the only component that knows a concrete format. Above it, the dynamic API, comment reconciliation
and binding are all format-agnostic.
| Codec | formatId |
Extensions | Comment fidelity | Notes |
|---|---|---|---|---|
YamlCodec |
yaml |
yml, yaml
|
LOSSLESS | block + side + header/footer comments round-trip |
JsonCodec |
json |
json |
NONE | strict RFC JSON, pretty-printed; comments not emitted |
TomlCodec |
toml |
toml |
LOSSLESS |
[table] sections + # comments; no null
|
JsoncCodec |
jsonc |
jsonc |
LOSSY | JSON with // comments; best-effort positions |
Config yaml = Config.open(Paths.get("a.yml"), new YamlCodec());
Config json = Config.open(Paths.get("a.json"), new JsonCodec());
Config toml = Config.open(Paths.get("a.toml"), new TomlCodec());
Config jsonc = Config.open(Paths.get("a.jsonc"), new JsoncCodec());CommentFidelity is a codec capability, not a global setting:
-
LOSSLESS— comments survive a full round-trip (YAML, TOML). -
LOSSY— best-effort; comments in positions the path-keyed overlay can address survive (JSONC). -
NONE— the format has no comment syntax that round-trips; comment writes are accepted in memory but not emitted, and the data is never corrupted (JSON).
Code that calls
setComment(...)is portable across all four codecs. ANONEcodec drops it on write; aLOSSLESS/LOSSYcodec round-trips it. The comment overlay lives onConfig, independent of the codec.
A custom format implements Codec (text ⇄ tree + identity) and, to carry comments, CommentAware (the
structure emitter + comment parser). ObjectMapperAware exposes the shared mapper for binding.
public interface Codec {
String formatId();
String[] fileExtensions(); // lowercase, no dot; first = canonical
CommentFidelity commentFidelity();
JsonNode readTree(String text); // text -> canonical tree (unknown keys survive)
String writeTreePlain(JsonNode t); // tree -> text, no structural comments
<V> V treeToValue(JsonNode n, JavaType t);
JsonNode valueToTree(Object v);
}The emitter renders document structure itself and delegates only leaf values to the mapper — it never re-parses the mapper's output, so a custom mapper can restyle a value without breaking layout or comments.
CodecRegistry registry = CodecRegistry.defaults(); // JSON, YAML, TOML, JSONC
Codec c = registry.forFile("server.toml"); // -> TomlCodec
Codec y = registry.byExtension("yml"); // -> YamlCodec
registry.register(new MyCustomCodec()); // last registration for an extension winsResolution is by extension only — it never content-sniffs (a YAML and a JSON document overlap, so guessing
is ambiguous). An unknown extension throws CodecException.
Block/side/header/footer comments and key order round-trip. Long scalars stay on one line (split disabled), no
leading --- marker. The comment parser is line-based and covers common block-style YAML; exotic constructs
(# inside a | block scalar, multi-line flow) are not specially handled.
Strict, pretty-printed RFC JSON. Explicit nulls are kept (they are user data). Comments are never emitted.
Nested objects become [table.path] sections (a table's own scalars are emitted before its sub-tables, as TOML
requires); # comments round-trip. TOML has no null — a null value is omitted on write (see
FAQ & Gotchas). A very large integer the TOML reader can't round-trip is stored as a quoted string so
it still reads back as the same digits.
JSON plus // (and /* */) comments and trailing commas on read; // block/side comments on write. Comment
positions the overlay can't address (e.g. between array elements) are not preserved — hence LOSSY.
→ See also Architecture Overview · FAQ & Gotchas
EveryConfig · br.com.finalcraft:EveryConfig · One config API, every format, comments included · made by Petrus Pradella
Getting Started
Core Concepts
Typed Binding
Operations
Reference
Contributing