Skip to content

Examples of custom types in your configuration

A248 edited this page Jun 13, 2021 · 4 revisions

You aren't limited to strings, integers, booleans, and the like. In fact, you can use any kind of object in your configuration, so long as it's either an interface or you can instantiate it. Here are two examples.

Simple Example

Firstly, you can implement a ValueSerialiser for your type. Here's a simple example.

The Config

public interface Config {

	@ConfDefault.DefaultString("default value")
	CustomType customType();
}

The ValueSerialiser implementation

public class MyCustomSerializer implements ValueSerialiser<CustomType> {
	@Override
	public Class<CustomType> getTargetClass() {
		return CustomType.class;
	}

	@Override
	public CustomType deserialise(FlexibleType flexibleType) throws BadValueException {
		// Convert from a String -> CustomType
		String value = flexibleType.getString();
		return new CustomType(value);
	}

	@Override
	public Object serialise(CustomType value, Decomposer decomposer) {
		// Convert from a CustomType -> String
		return value.stringValue();
	}
}

You'll need to add the ValueSerializer to your ConfigurationOptions when you create your configuration factory. This example uses Hocon:

		ConfigurationOptions options = new ConfigurationOptions.Builder()
				.addSerialiser(new MyCustomSerializer())
				.build();
		ConfigurationFactory<Config> factory = HoconConfigurationFactory.create(Config.class, options).loadDefaults();

A more complex object

Here's another example asked about in https://github.com/A248/DazzleConf/issues/25.

public interface Config {

   static Map<Integer, Level> defaultLevels() {
        Map<Integer, Level> levelsMap = new HashMap<>();
        levelsMap.put(1, Level.of(5, 10, 1, 10, 0));
        levelsMap.put(2, Level.of(7, 12, 2, 11, 10));
        levelsMap.put(3, Level.of(9, 14, 3, 12, 20));
        levelsMap.put(4, Level.of(12, 16, 4, 13, 30));
        levelsMap.put(5, Level.of(15, 18, 5, 14, 40));
        return levelsMap;
    }

    @ConfDefault.DefaultObject("defaultLevels")
    // The @SubSection here is important
    Map<Integer, @SubSection Level> levels();

}
public interface Level {

	int minSpawnDelay();

	int maxSpawnDelay();

	int spawnCount();

	int spawnRange();

	int price();

	static Level of(int minSpawnDelay, int maxSpawnDelay, int spawnCount, int spawnRange, int price) {
		return new Level() {

			@Override
			public int minSpawnDelay() { return minSpawnDelay; }
			@Override
			public int maxSpawnDelay() { return maxSpawnDelay; }
			@Override
			public int spawnCount() { return spawnCount; }
			@Override
			public int spawnRange() { return spawnRange; }
			@Override
			public int price() { return price; }
		};
	}

}

If you use this config with YAML, you'll receive:

levels:
  1:
    minSpawnDelay: 5
    maxSpawnDelay: 10
    spawnCount: 1
    spawnRange: 10
    price: 0
  # etc., for each level