Config
Config is an immutable, untyped view over a parsed HOCON document. You obtain one from Hocon.parse, navigate it by dot-separated path, and read typed values with the getters below.
Config is an immutable, untyped view over a parsed HOCON document. You obtain one from
Hocon.parse, navigate it by dot-separated path, and read typed values with the getters
below.
Parsing and combining
These live on the Hocon object.
| Method | Returns | Description |
|---|---|---|
Hocon.parse(input: String) | Config | Parse HOCON source and resolve ${...} substitutions. Throws ParseError on a syntax error. |
Hocon.parse(input: String, env: EnvSource) | Config | As above, falling back to env for substitutions absent from the document. |
Hocon.parse(input: String, source: ConfigSource) | Config | As above, loading include directives through source. |
Hocon.parse(input: String, env: EnvSource, source: ConfigSource) | Config | Both seams supplied. |
Hocon.parseValue(input: String) | ConfigValue | Parse and resolve a document whose root may be an object or an array, returning the root value directly. Same optional env/source overloads as parse. |
Hocon.load(configs: Config*) | Config | Merge configs so that later arguments win. No arguments → the empty config. |
Per the HOCON spec a document’s root may be an object or an array. Hocon.parse returns the
path-addressable Config and requires an object root — it raises WrongTypeException on a
top-level array. When the input is (or may be) a top-level array, use Hocon.parseValue, which
returns the resolved root ConfigValue (ConfigObject or ConfigArray). Inside an array root
there are no keys to look into, so only ${?...} and environment fallbacks resolve.
EnvSource is the seam substitutions use for environment fallback. The default is
EnvSource.empty; build one from a map with EnvSource.fromMap(...), use EnvSource.system
for the real process environment, or implement the single-method trait yourself. See the
substitutions guide.
ConfigSource is the seam include directives use to read other documents. The default is
ConfigSource.empty (no IO — optional includes are skipped, a required(...) one raises);
ConfigSource.fromMap(...) resolves includes from an in-memory map, and ConfigSource.default
reads the filesystem identically on every platform. url(...) and classpath(...) qualifiers
are recognised but not served by the default — pass a custom source for those. See the
format guide.
import io.github.edadma.hocon.*
val config = Hocon.parse("""a = 1, b { c = 2 }""")
Reading values
Paths are dot-separated (a.b.c). Each getter throws MissingPathException when the path is
absent or null, and WrongTypeException when the value is the wrong shape.
| Method | Returns | Notes |
|---|---|---|
getString(path) | String | Numbers and booleans are returned as their text. |
getInt(path) | Int | Parses the numeric literal. |
getLong(path) | Long | |
getDouble(path) | Double | |
getBoolean(path) | Boolean | Also accepts the strings yes/no/on/off. |
getConfig(path) | Config | The sub-object at path. |
getList(path) | List[ConfigValue] | The raw array elements. |
getStringList(path) | List[String] | Each element coerced to string. |
getDuration(path) | FiniteDuration | A HOCON duration (10s, 5 minutes); a bare number is milliseconds. |
getBytes(path) | Long | A HOCON size in bytes (512K, 10MB); powers of 1024 and 1000 are distinguished. |
getValue(path) | ConfigValue | The raw value node, whatever its type. |
config.getInt("a") // 1
config.getInt("b.c") // 2
config.getConfig("b").getInt("c") // 2
Durations and sizes
getDuration reads a HOCON time value into a cross-platform
scala.concurrent.duration.FiniteDuration. Units are ns, us, ms, s, m, h, d and
their long spellings; a number with no unit is read as milliseconds.
getBytes reads a HOCON memory size into a Long count of bytes. Powers-of-1024 units (K,
Ki, KiB, …) and powers-of-1000 units (kB, MB, …) are distinguished per the spec; a bare
number is a byte count, and a fractional quantity truncates.
val c = Hocon.parse("timeout = 30s, cache = 512K")
c.getDuration("timeout") // 30.seconds
c.getBytes("cache") // 524288
Optional access
hasPath reports whether a path resolves to a present, non-null value. Each getter has an
*Opt variant that returns None instead of throwing on a missing path:
| Method | Returns |
|---|---|
hasPath(path) | Boolean |
getStringOpt(path) | Option[String] |
getIntOpt(path) | Option[Int] |
getLongOpt(path) | Option[Long] |
getDoubleOpt(path) | Option[Double] |
getBooleanOpt(path) | Option[Boolean] |
getConfigOpt(path) | Option[Config] |
getListOpt(path) | Option[List[ConfigValue]] |
getDurationOpt(path) | Option[FiniteDuration] |
getBytesOpt(path) | Option[Long] |
config.hasPath("b.c") // true
config.getStringOpt("nope") // None
Merging
| Method | Returns | Description |
|---|---|---|
withFallback(other: Config) | Config | This config wins; other supplies defaults for keys this config lacks. Objects merge recursively; arrays and scalars replace. |
See the merging guide for the full semantics.
The value tree
getValue and getList hand back ConfigValue nodes — the raw, untyped tree:
ConfigObject(fields: Map[String, ConfigValue])ConfigArray(elements: List[ConfigValue])ConfigString(value: String)ConfigNumber(raw: String)— the original literal text, parsed on demandConfigBoolean(value: Boolean)ConfigNull
Config.root exposes the top-level ConfigObject directly.
Typed decoding
Map a config onto a case class instead of reading fields one at a time. A Decoder[A] is
derived automatically for any case class — and case classes nested inside it — from its
Mirror, so there is nothing to write but the class.
| Method | Returns | Description |
|---|---|---|
as[A] | A | Decode the whole config into A, mapping each field to the top-level key of the same name. |
getAs[A](path) | A | Decode the value at path into A. |
case class Server(host: String, port: Int, debug: Boolean)
val config = Hocon.parse("host = localhost, port = 8080, debug = true")
config.as[Server] // Server("localhost", 8080, true)
config.getAs[Server]("server") // decode a nested object at a path
Field types supported out of the box: String, Int, Long, Double, Boolean,
FiniteDuration, Option[A] (absent or null → None), List[A], Map[String, A],
Config, the raw ConfigValue, and nested case classes. A missing required field throws
MissingPathException and a wrongly-typed one throws WrongTypeException, each carrying the
dotted field path. See the decoding guide for the full story.
Exceptions
All errors extend HoconException:
ParseError(message, line, col)— a syntax error, with 1-based source position.MissingPathException(path)— nothing at the requested path (or it isnull).WrongTypeException(path, expected, found)— the value is the wrong type for the getter.UnresolvedSubstitutionException(path)— a required${path}found in neither the config nor the environment.CircularReferenceException(chain)— substitutions reference each other in a cycle.HoconConcatException(message)— a value concatenation mixes incompatible kinds, such as an object or array joined with a string.IncludeException(message)— arequired(...)include resolved to nothing, or a cycle of files includes one another.