Class HoconLoader
- All Implemented Interfaces:
Serializable,Loader
loader for HOCON,
reading a source whose path ends in .conf.
server {
host = localhost
port = 8080
}
servers = [ { host = alpha }, { host = beta } ]
server.host=localhost
server.port=8080
servers[0].host=alpha
servers[1].host=beta
The keys are the ones every loader in this library flattens to, so a HOCON document is read by the same nested interfaces, indexed lists and grouped maps as anything else.
Why this one is not written by hand
Every other format this project reads has a parser of its own, written here, with no dependency. HOCON is
the exception, and the reason is not its size. HOCON's specification is an implementation: there is
one, Lightbend's, and the value of the format is reading the application.conf files people
already have. Its substitutions - ${foo} and ${?foo} - resolve after the whole
merge, across files, and may be self-referential; objects with the same key merge rather than replace one
another; include pulls in another document mid-parse. A subset that refused all of that would
be JSON with comments, which is not why anybody chooses HOCON.
And this library already reads ${...}, with different semantics and at a different time. A
hand-written approximation would therefore not fail on the files it cannot handle - it would read them
and quietly mean something else, which is worse than not supporting the format. So this adapts the
reference implementation, and what a HOCON document means here is what it means everywhere.
What it costs, and to whom
Nothing, unless a .conf source is read. com.typesafe:config is an
optional dependency of owner-extras: it is not transitive, this project does not ship it,
and nobody receives it by depending on OWNER. Nothing in this class names it - everything that does lives
in HoconReader, which is not touched until a document is actually read - so this loader is
discovered and instantiated on a class path without it, like any other, and only a configuration naming a
.conf source is told, by name and with what to add, that the dependency is missing. It
contributes .conf to the file names tried when a configuration declares no
@Sources, and probing for a file that is not there costs no more than any other probe.
See HoconReader for why that separation must not be undone.
Two things to know about the values
A value comes back as the reference implementation understood it, not as it was written. Elsewhere
in this library the text is kept exactly - our JSON reader answers 1e3 for 1e3 -
because those parsers hand over the characters. Typesafe Config parses eagerly into typed values and does
not keep the original text, so 1e3 arrives here as 1000 and 1.50 as
1.5. Nothing a converter needs is lost, and a string, a duration like 10s or a
size like 512K is untouched, those being strings in HOCON's own model. It is stated because
it cannot be seen.
A null writes no key at all, as it does for JSON: a Properties cannot hold
one, and HOCON's own reading API treats a null as missing. So a @DefaultValue wins over a
null written on purpose. Leave the key out of the document when that matters.
- Since:
- 2.0.0
- Author:
- Matteo Baccan
- See Also:
-
Constructor Summary
ConstructorsConstructorDescriptionA loader is built with no arguments, both when it is registered by hand and whenServiceLoaderfinds it on the class path. -
Method Summary
Modifier and TypeMethodDescriptionbooleanIndicates whether this Loader accepts the URI, guessing the content type from it.defaultSpecFor(String uriPrefix) Returns the default URI specification for a given URI resource, that can be handled by this loader.voidload(Properties result, URI uri) Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface org.aeonbits.owner.loaders.Loader
defaultSpecsFor
-
Constructor Details
-
HoconLoader
public HoconLoader()A loader is built with no arguments, both when it is registered by hand and whenServiceLoaderfinds it on the class path. Declared rather than left implicit so that the requirement is visible to whoever changes this class.
-
-
Method Details
-
accept
Description copied from interface:LoaderIndicates whether this Loader accepts the URI, guessing the content type from it. -
load
Description copied from interface:Loader- Specified by:
loadin interfaceLoader- Parameters:
result- the resulting properties where to load theuriuri- theURIfrom where to load the properties.- Throws:
IOException- if there is some I/O error during the load.
-
defaultSpecFor
Description copied from interface:LoaderReturns the default URI specification for a given URI resource, that can be handled by this loader.Returning
nullmeans this loader adds nothing to the sources looked for in the absence of@Sources- which is whatSystemLoaderandDotEnvLoaderboth do, since neither is named after the configuration interface. That is also why this method has a default: it is a choice a loader is allowed to decline, and declining it should not require writing a method that returns nothing.A loader offering more than one name - a format spelled
.yamland.yml, or.iniand.cfg- overridesLoader.defaultSpecsFor(String)instead. The two are not meant to be overridden together.- Specified by:
defaultSpecForin interfaceLoader- Parameters:
uriPrefix- the prefix identifying the URI resource.- Returns:
- the default URI specification for a given URI resource, or
nullfor none.
-