-
Notifications
You must be signed in to change notification settings - Fork 0
Dynamic API
The dynamic API operates directly on the canonical ObjectNode using dot-separated paths. Typed getters route
through a single coercion seam (NodeCoercion), so "what does getInt do to a string node" is defined in one
place.
cfg.setValue("a.b.c", 42); // auto-vivifies intermediate objects (only objects, never arrays)
cfg.setValue("a.b.c", null); // a Java null DELETES the entry
cfg.setValue("", someObjectNode); // replaces the whole root (must be an object)
cfg.setValue("note", "hi", "a comment"); // value + comment in one call
boolean removed = cfg.removeValue("a.b"); // returns true if it existed; drops the subtree's comments
cfg.migrateKey("old.path", "new.path"); // move data + its full comment subtree to a new pathReplacing a container subtree drops the comments of its descendants (they no longer apply).
migrateKey is the explicit rename hook for a config migration (reconciliation never infers a rename).
It carries the key's own block/side comment AND those of every descendant path, written as
authoritative so they are preserved (not re-seeded). A root path, an equal path, or an absent source is a
no-op.
Each getter has a zero-default form and a (path, default) form:
cfg.getString("name"); cfg.getString("name", "fallback");
cfg.getInt("port"); cfg.getInt("port", 25565);
cfg.getLong("ts"); cfg.getLong("ts", 0L);
cfg.getDouble("ratio"); cfg.getDouble("ratio", 1.0);
cfg.getBoolean("pvp"); cfg.getBoolean("pvp", true);
cfg.getStringList("tags"); cfg.getStringList("tags", defaultList);
cfg.getList("items", Integer.class); // typed; empty (never null) when absent / not a list
cfg.getValue("db", Db.class); // a subtree bound to a type (POJO or scalar)
cfg.getUUID("id"); cfg.getUUID("id", fallbackUuid);-
getStringon a list joins elements with\n; on an object it returnstoString(). -
getStringList(path)returns an empty list when absent;getStringList(path, def)returnsdefonly when the path is absent.
Legacy long-as-string tolerance. The numeric getters parse a number stored as a quoted string:
getLong("1700000000000")→ the long,getLong("1.0")→1,getInt("25565")→25565. An empty string reads as the default.
These three states are distinct:
cfg.setValue("present", 5);
cfg.getRoot().putNull("explicitNull"); // present, but null
cfg.contains("missing"); // false — absent
cfg.getValue("missing"); // null
cfg.getInt("missing", 9); // 9
cfg.contains("explicitNull"); // true — present but null
cfg.getValue("explicitNull"); // null
cfg.getInt("explicitNull", 9); // 9 (a null flattens to the default)
cfg.contains("present"); // true — a real value
cfg.getInt("present"); // 5cfg.contains("a.b"); // does the path resolve?
cfg.getKeys(); // direct child keys of the root
cfg.getKeys("server"); // direct child keys of "server"
cfg.getKeys("", true); // DEEP — dotted descendant paths
cfg.getConfigSection("a"); // always a view; use cfg.contains("a") for existence
cfg.getConfigSection("a"); // ALWAYS a (possibly empty) viewA ConfigSection is a scoped cursor: every method delegates to the owning Config with the section's path
prefixed.
ConfigSection db = cfg.getConfigSection("database");
db.setValue("url", "jdbc:..."); // writes "database.url"
db.getInt("pool.size"); // reads "database.pool.size"
db.getSectionKey(); // "database"getValue(path, type) binds the subtree at a dotted path to a fresh POJO — the path-scoped form of
loadAs. The 2-arg form uses the codec the config was opened with; pass a Codec to override it.
DbConfig db = cfg.getValue("database", DbConfig.class); // bind the "database" subtree
DbConfig db = cfg.getValue("database", DbConfig.class, yamlCodec);
cfg.getValue("missing", DbConfig.class); // absent path → the type's defaults
cfg.getValue("", Root.class); // root path ("" or null) → the whole treeThe 2-arg form throws
IllegalStateExceptionif the config was built without a codec (new Config()). The full binding model (@Key,@Comment,@Section, lenient vs. strict,LoadIssues) lives in Entity Binding.
getRoot() exposes the live ObjectNode — the single source of truth. Mutate it directly when you need raw
Jackson; the dynamic API and binding both see the change, and unknown keys you add survive every save.
cfg.getRoot().put("rawKey", "set outside the API");→ See also Default Values & Comments · Entity Binding
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