General implementations based on standard format libraries directly.
Special implementations for safe use in specific environment, eg. gameservers.
For standalone platforms
hjson module is the best choice, it supports all the features, eg. full comment support.
Combine it with Okaeri Validator for the best config experience.
Total of only ~155kB, less than half of just the latest snakeyaml 1.28 which is 319kB!
For any platform
if some form of config validation is applicable (eg. requiring that integer is positive) it is recommended to use Okaeri Validator when possible.
Only few kilobytes but makes for a lot better experience for the end-user and developer too.
For any platform
if some form of the i18n/translation is needed, you may be interested in okaeri-i18n which can use okaeri-configs as a translation source.
Okaeri's configuration library is an easy way to use java classes as config adapters:
// getter/setter from lombok recommended
@Header("################################################################")
@Header("# #")
@Header("# okaeri-configs test #")
@Header("# #")
@Header("# Nie wiesz jak uzywac? Zerknij do dokumentacji! #")
@Header("# https://github.com/OkaeriPoland/okaeri-configs #")
@Header("# #")
@Header("# Trouble using? Check out the documentation! #")
@Header("# https://github.com/OkaeriPoland/okaeri-configs #")
@Header("# #")
@Header("################################################################")
// optional global key formatting (may yield unexpected names, use at own risk)
// @Names(strategy = NameStrategy.HYPHEN_CASE, modifier = NameModifier.TO_LOWER_CASE)
public class TestConfig extends OkaeriConfig {
@Variable("APP_TOKEN") // use jvm property or environment variable if available
@Comment({"Klucz prywatny API", "API secret"})
private String token = "";
@CustomKey("myList")
@Comment({"Example list", "providing @CustomKey demonstration"})
private List<String> exampleList = Collections.singletonList("127.0.0.1");
@Comment({"Simple maps", "ready to go"})
private Map<String, String> messages = Collections.singletonMap("test", "testing");
@Comment({"Test complex map 1", "looks like complex maps are working too"})
private Map<String, Map<String, Integer>> complexMap = Collections.singletonMap("aa", Collections.singletonMap("bb", 222));
@Comment("Test complex map 2")
private Map<String, Map<Integer, String>> complexMap2 = Collections.singletonMap("bb", Collections.singletonMap(232, "aadda"));
@Comment("Custom objects can be serialized")
private Location spawn = new Location(null, 1, 2, 3, 4, 5);
@Comment("Non-string map keys")
private Map<Integer, String> levels = Collections.singletonMap(1, "aaaaaa");
@Comment("okaeri-configs likes classes more than primitives")
private Integer version = 2;
@Comment({"Test enum", "very nice", "right?"})
private TestEnum testEnum = TestEnum.ONE_THO_THREE;
@Comment("Test enum list")
private List<TestEnum> testEnumList = Arrays.asList(TestEnum.ONE, TestEnum.ONE_THO_THREE);
@Comment("Test enum set")
private Set<TestEnum> testEnumSet = new HashSet<>(Arrays.asList(TestEnum.ONE, TestEnum.ONE_THO_THREE));
@Comment("Test custom object list")
@Comment(".. and repeating comments")
private List<Location> testLocationList = Arrays.asList(
new Location(null, 1, 2, 3, 4, 5),
new Location(null, 3, 3, 5, 6, 9)
);
@Comment("Uber-complex-map test")
private Map<TestEnum, Location> enumToLocationMap = Collections.singletonMap(TestEnum.THREE, new Location(null, 1, 2, 3, 4, 5));
@CustomKey("listToUberComplexMap")
@Comment("List-to-Uber-complex-map test")
private List<Map<TestEnum, Location>> listMapEnumToLocationMap = Arrays.asList(
Collections.singletonMap(TestEnum.THREE, new Location(null, 1, 2, 3, 4, 5)),
Collections.singletonMap(TestEnum.ONE_THO_THREE, new Location(null, 3, 2, 3, 4, 5))
);
@Comment("Math test")
private BigInteger bigInteger = new BigInteger("999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999876543210");
@Comment("Subconfigs are the way!")
private StorageConfig storage = new StorageConfig();
// getter/setter from lombok recommended
public class StorageConfig extends OkaeriConfig {
@Variable("APP_STORAGE_URI")
@Comment("FLAT : not applicable, plugin controlled")
@Comment("REDIS : redis://localhost")
@Comment("MYSQL : jdbc:mysql://localhost:3306/db?user=root&password=1234")
@Comment("H2 : jdbc:h2:file:./plugins/OkaeriPlatformBukkitExample/storage;mode=mysql")
private String uri = "redis://localhost";
/* ... */
}
// in-memory only field
private transient Instant start = Instant.now();
/* ... */
}
// recommended
TestConfig config = ConfigManager.create(TestConfig.class, (it) -> {
it.withConfigurer(new YamlBukkitConfigurer(), new SerdesBukkit()); // specify configurer implementation, optionally additional serdes packages
it.withBindFile(new File(this.getDataFolder(), "config.yml")); // specify Path, File or pathname
it.withRemoveOrphans(true); // automatic removal of undeclared keys
it.saveDefaults(); // save file if does not exists
it.load(true); // load and save to update comments/new fields
});
TestConfig config = (TestConfig) ConfigManager.create(TestConfig.class)
.withConfigurer(new YamlBukkitConfigurer(), new SerdesBukkit()) // specify configurer implementation, optionally additional serdes packages
.withBindFile(new File(this.getDataFolder(), "config.yml")) // specify Path, File or pathname
.withRemoveOrphans(true); // automatic removal of undeclared keys
.saveDefaults() // save file if does not exists
.load(true); // load and save to update comments/new fields
java.math.BigInteger
, java.math.BigDecimal
Map<K, V>
: results in LinkedHashMapSet<T>
: results in LinkedHashSetList<T>
: results in ArrayListvalueOf()
(with case-insensitive fallback) and name()
ObjectSerializer
/ObjectTransformer
(see in supported platforms)