hocon

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.

MethodReturnsDescription
Hocon.parse(input: String)ConfigParse HOCON source and resolve ${...} substitutions. Throws ParseError on a syntax error.
Hocon.parse(input: String, env: EnvSource)ConfigAs above, falling back to env for substitutions absent from the document.
Hocon.parse(input: String, source: ConfigSource)ConfigAs above, loading include directives through source.
Hocon.parse(input: String, env: EnvSource, source: ConfigSource)ConfigBoth seams supplied.
Hocon.parseValue(input: String)ConfigValueParse 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*)ConfigMerge 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.

MethodReturnsNotes
getString(path)StringNumbers and booleans are returned as their text.
getInt(path)IntParses the numeric literal.
getLong(path)Long
getDouble(path)Double
getBoolean(path)BooleanAlso accepts the strings yes/no/on/off.
getConfig(path)ConfigThe sub-object at path.
getList(path)List[ConfigValue]The raw array elements.
getStringList(path)List[String]Each element coerced to string.
getDuration(path)FiniteDurationA HOCON duration (10s, 5 minutes); a bare number is milliseconds.
getBytes(path)LongA HOCON size in bytes (512K, 10MB); powers of 1024 and 1000 are distinguished.
getValue(path)ConfigValueThe 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:

MethodReturns
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

MethodReturnsDescription
withFallback(other: Config)ConfigThis 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 demand
  • ConfigBoolean(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.

MethodReturnsDescription
as[A]ADecode the whole config into A, mapping each field to the top-level key of the same name.
getAs[A](path)ADecode 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 nullNone), 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 is null).
  • 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) — a required(...) include resolved to nothing, or a cycle of files includes one another.

Search

Esc
to navigate to open Esc to close