class Config

An immutable map from config paths to config values. Paths are dot-separated expressions such as foo.bar.baz. Values are as in JSON (booleans, strings, numbers, lists, or objects), represented by {@link ConfigValue} instances. Values accessed through the Config interface are never null.

<p> {@code Config} is an immutable object and thus safe to use from multiple threads. There’s never a need for “defensive copies.”

<p> Fundamental operations on a {@code Config} include getting configuration values, resolving substitutions with {@link Config#resolve()}, and merging configs using {@link Config#withFallback(ConfigMergeable)}.

<p> All operations return a new immutable {@code Config} rather than modifying the original instance.

<p> <strong>Examples</strong>

<p> You can find an example app and library <a href=“github.com/typesafehub/config/tree/master/examples”>on GitHub</a>. Also be sure to read the <a href=“package-summary.html#package_description”>package overview</a> which describes the big picture as shown in those examples.

<p> <strong>Paths, keys, and Config vs. ConfigObject</strong>

<p> Config is a view onto a tree of {@link ConfigObject}; the corresponding object tree can be found through {@link Config#root()}. ConfigObject is a map from config keys, rather than paths, to config values. Think of ConfigObject as a JSON object and Config as a configuration API.

<p> The API tries to consistently use the terms “key” and “path.” A key is a key in a JSON object; it’s just a string that’s the key in a map. A “path” is a parseable expression with a syntax and it refers to a series of keys. Path expressions are described in the <a href=“github.com/typesafehub/config/blob/master/HOCON.md”>spec for Human-Optimized Config Object Notation</a>. In brief, a path is period-separated so “a.b.c” looks for key c in object b in object a in the root object. Sometimes double quotes are needed around special characters in path expressions.

<p> The API for a {@code Config} is in terms of path expressions, while the API for a {@code ConfigObject} is in terms of keys. Conceptually, {@code Config} is a one-level map from paths to values, while a {@code ConfigObject} is a tree of nested maps from keys to values.

<p> Use {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath} to convert between path expressions and individual path elements (keys).

<p> Another difference between {@code Config} and {@code ConfigObject} is that conceptually, {@code ConfigValue}s with a {@link ConfigValue#valueType() valueType()} of {@link ConfigValueType#NULL NULL} exist in a {@code ConfigObject}, while a {@code Config} treats null values as if they were missing.

<p> <strong>Getting configuration values</strong>

<p> The “getters” on a {@code Config} all work in the same way. They never return null, nor do they return a {@code ConfigValue} with {@link ConfigValue#valueType() valueType()} of {@link ConfigValueType#NULL NULL}. Instead, they throw {@link ConfigException.Missing} if the value is completely absent or set to null. If the value is set to null, a subtype of {@code ConfigException.Missing} called {@link ConfigException.Null} will be thrown. {@link ConfigException.WrongType} will be thrown anytime you ask for a type and the value has an incompatible type. Reasonable type conversions are performed for you though.

<p> <strong>Iteration</strong>

<p> If you want to iterate over the contents of a {@code Config}, you can get its {@code ConfigObject} with {@link root()}, and then iterate over the {@code ConfigObject} (which implements java.util.Map). Or, you can use {@link entrySet()} which recurses the object tree for you and builds up a Set of all path-value pairs where the value is not null.

<p> <strong>Resolving substitutions</strong>

<p> Substitutions are the ${foo.bar} syntax in config files, described in the <a href= “github.com/typesafehub/config/blob/master/HOCON.md#substitutions” >specification</a>. Resolving substitutions replaces these references with real values.

<p> Before using a {@code Config} it’s necessary to call {@link Config#resolve()} to handle substitutions (though {@link ConfigFactory#load()} and similar methods will do the resolve for you already).

<p> <strong>Merging</strong>

<p> The full Config for your application can be constructed using the associative operation {@link Config#withFallback(ConfigMergeable)}. If you use {@link ConfigFactory#load()} (recommended), it merges system properties over the top of application.conf over the top of reference.conf, using withFallback. You can add in additional sources of configuration in the same way (usually, custom layers should go either just above or just below application.conf, keeping reference.conf at the bottom and system properties at the top).

<p> <strong>Serialization</strong>

<p> Convert a Config to a JSON or HOCON string by calling {@link ConfigObject#render()} on the root object, myConfig.root().render(). There’s also a variant {@link ConfigObject#render(ConfigRenderOptions)} which allows you to control the format of the rendered string. (See {@link ConfigRenderOptions}.) Note that Config does not remember the formatting of the original file, so if you load, modify, and re-save a config file, it will be substantially reformatted.

<p> As an alternative to {@link ConfigObject#render()}, the toString() method produces a debug-output-oriented representation (which is not valid JSON).

<p> Java serialization is supported as well for Config and all subtypes of ConfigValue.

<p> <strong>This is an interface but don’t implement it yourself</strong>

<p> Do not implement {@code Config}; it should only be implemented by the config library. Arbitrary implementations will not work because the library internals assume a specific concrete implementation. Also, this interface is likely to grow new methods over time, so third-party implementations will break.