{"id":13445855,"url":"https://github.com/lightbend/config","last_synced_at":"2025-12-16T20:48:52.770Z","repository":{"id":1990756,"uuid":"2923236","full_name":"lightbend/config","owner":"lightbend","description":"configuration library for JVM languages using HOCON files","archived":false,"fork":false,"pushed_at":"2024-08-19T20:31:15.000Z","size":4635,"stargazers_count":6227,"open_issues_count":237,"forks_count":964,"subscribers_count":193,"default_branch":"main","last_synced_at":"2025-05-03T03:08:23.234Z","etag":null,"topics":["configuration-library","hocon","supported"],"latest_commit_sha":null,"homepage":"https://lightbend.github.io/config/","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lightbend.png","metadata":{"files":{"readme":"README.md","changelog":"NEWS.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE-2.0.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2011-12-06T08:02:29.000Z","updated_at":"2025-04-29T13:05:39.000Z","dependencies_parsed_at":"2023-07-07T07:33:25.531Z","dependency_job_id":"994fc889-2143-4148-aed4-f5de85e105c9","html_url":"https://github.com/lightbend/config","commit_stats":{"total_commits":866,"total_committers":110,"mean_commits":7.872727272727273,"dds":0.3163972286374134,"last_synced_commit":"d279841c425e70645feacbdc03e41b3b022ad1f9"},"previous_names":["typesafehub/config"],"tags_count":33,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lightbend%2Fconfig","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lightbend%2Fconfig/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lightbend%2Fconfig/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lightbend%2Fconfig/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lightbend","download_url":"https://codeload.github.com/lightbend/config/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252721001,"owners_count":21793745,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["configuration-library","hocon","supported"],"created_at":"2024-07-31T05:00:40.713Z","updated_at":"2025-12-16T20:48:52.762Z","avatar_url":"https://github.com/lightbend.png","language":"Java","readme":"# Configuration library for JVM languages.\n\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.typesafe/config/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.typesafe/config)\n[![Build Status](https://github.com/lightbend/config/actions/workflows/ci.yml/badge.svg)](https://github.com/lightbend/config/actions/workflows/ci.yml)\n\n## Overview\n\n - implemented in plain Java with no dependencies\n - supports files in three formats: Java properties, JSON, and a\n   human-friendly JSON superset\n - merges multiple files across all formats\n - can load from files, URLs, or classpath\n - good support for \"nesting\" (treat any subtree of the config the\n   same as the whole config)\n - users can override the config with Java system properties,\n    `java -Dmyapp.foo.bar=10`\n - supports configuring an app, with its framework and libraries,\n   all from a single file such as `application.conf`\n - parses duration and size settings, \"512k\" or \"10 seconds\"\n - converts types, so if you ask for a boolean and the value\n   is the string \"yes\", or you ask for a float and the value is\n   an int, it will figure it out.\n - JSON superset features:\n    - comments\n    - includes\n    - substitutions (`\"foo\" : ${bar}`, `\"foo\" : Hello ${who}`)\n    - properties-like notation (`a.b=c`)\n    - less noisy, more lenient syntax\n    - substitute environment variables (`logdir=${HOME}/logs`)\n - API based on immutable `Config` instances, for thread safety\n   and easy reasoning about config transformations\n - extensive test coverage\n\nThis library limits itself to config files. If you want to load\nconfig from a database or something, you would need to write some\ncustom code. The library has nice support for merging\nconfigurations so if you build one from a custom source it's easy\nto merge it in.\n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [Essential Information](#essential-information)\n  - [License](#license)\n  - [Binary Releases](#binary-releases)\n  - [Release Notes](#release-notes)\n  - [API docs](#api-docs)\n  - [Bugs and Patches](#bugs-and-patches)\n  - [Build](#build)\n- [Using the Library](#using-the-library)\n  - [API Example](#api-example)\n  - [Longer Examples](#longer-examples)\n  - [Immutability](#immutability)\n  - [Schemas and Validation](#schemas-and-validation)\n  - [Standard behavior](#standard-behavior)\n    - [Note about resolving substitutions in `reference.conf` and `application.conf`](#note-about-resolving-substitutions-in-referenceconf-and-applicationconf)\n  - [Merging config trees](#merging-config-trees)\n  - [How to handle defaults](#how-to-handle-defaults)\n  - [Understanding `Config` and `ConfigObject`](#understanding-config-and-configobject)\n  - [ConfigBeanFactory](#configbeanfactory)\n- [Using HOCON, the JSON Superset](#using-hocon-the-json-superset)\n  - [Features of HOCON](#features-of-hocon)\n  - [Examples of HOCON](#examples-of-hocon)\n  - [Uses of Substitutions](#uses-of-substitutions)\n    - [Factor out common values](#factor-out-common-values)\n    - [Inheritance](#inheritance)\n    - [Optional system or env variable overrides](#optional-system-or-env-variable-overrides)\n  - [Concatenation](#concatenation)\n- [Miscellaneous Notes](#miscellaneous-notes)\n  - [Debugging Your Configuration](#debugging-your-configuration)\n  - [Supports Java 8 and Later](#supports-java-8-and-later)\n  - [Rationale for Supported File Formats](#rationale-for-supported-file-formats)\n  - [Other APIs (Wrappers, Ports and Utilities)](#other-apis-wrappers-ports-and-utilities)\n    - [Guice integration](#guice-integration)\n    - [Java (yep!) wrappers for the Java library](#java-yep-wrappers-for-the-java-library)\n    - [Scala wrappers for the Java library](#scala-wrappers-for-the-java-library)\n    - [Clojure wrappers for the Java library](#clojure-wrappers-for-the-java-library)\n    - [Kotlin wrappers for the Java library](#kotlin-wrappers-for-the-java-library)\n    - [Scala port](#scala-port)\n    - [Ruby port](#ruby-port)\n    - [Puppet module](#puppet-module)\n    - [Python port](#python-port)\n    - [C++ port](#c-port)\n    - [JavaScript port](#javascript-port)\n    - [C# port](#c-port-1)\n    - [Go port](#go-port)\n    - [Linting tool](#linting-tool)\n    - [Online playground](#online-playground)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n## Essential Information\n\n### Binary Releases\n\nTypesafe Config is compatible with Java 8 and above.\n\nYou can find published releases on Maven Central.\n\n    \u003cdependency\u003e\n        \u003cgroupId\u003ecom.typesafe\u003c/groupId\u003e\n        \u003cartifactId\u003econfig\u003c/artifactId\u003e\n        \u003cversion\u003e1.4.4\u003c/version\u003e\n    \u003c/dependency\u003e\n\nsbt dependency:\n\n    libraryDependencies += \"com.typesafe\" % \"config\" % \"1.4.4\"\n\nLink for direct download if you don't use a dependency manager:\n\n - https://repo1.maven.org/maven2/com/typesafe/config/\n\n### Release Notes\n\nPlease see NEWS.md in this directory,\nhttps://github.com/lightbend/config/blob/main/NEWS.md\n\n### API docs\n\n - Online: https://lightbend.github.io/config/latest/api/\n - also published in jar form\n - consider reading this README first for an intro\n - for questions about the `.conf` file format, read\n   [HOCON.md](https://github.com/lightbend/config/blob/main/HOCON.md)\n   in this directory\n\n### Bugs and Patches\n\n**NOTE: Please read [Readme #Maintained-by](https://github.com/lightbend/config#Maintained-by) before spending time suggesting changes to this library.**\n\nReport bugs to the GitHub issue tracker. Send patches as pull\nrequests on GitHub.\n\nBefore we can accept pull requests, you will need to agree to the\nTypesafe Contributor License Agreement online, using your GitHub\naccount - it takes 30 seconds.  You can do this at\nhttps://www.lightbend.com/contribute/cla\n\nPlease see\n[CONTRIBUTING](https://github.com/lightbend/config/blob/main/CONTRIBUTING.md)\nfor more including how to make a release.\n\n### Build\n\nThe build uses sbt and the tests are written in Scala; however,\nthe library itself is plain Java and the published jar has no\nScala dependency.\n\n## Using the Library\n\n### API Example\n    import com.typesafe.config.ConfigFactory\n\n    Config conf = ConfigFactory.load();\n    int bar1 = conf.getInt(\"foo.bar\");\n    Config foo = conf.getConfig(\"foo\");\n    int bar2 = foo.getInt(\"bar\");\n\n### Longer Examples\n\nSee the examples in the `examples/` [directory](https://github.com/lightbend/config/tree/main/examples).\n\nYou can run these from the sbt console with the commands `project\nconfig-simple-app-java` and then `run`.\n\nIn brief, as shown in the examples:\n\n - libraries should use a `Config` instance provided by the app,\n   if any, and use `ConfigFactory.load()` if no special `Config`\n   is provided. Libraries should put their defaults in a\n   `reference.conf` on the classpath.\n - apps can create a `Config` however they want\n   (`ConfigFactory.load()` is easiest and least-surprising), then\n   provide it to their libraries. A `Config` can be created with\n   the parser methods in `ConfigFactory` or built up from any file\n   format or data source you like with the methods in\n   `ConfigValueFactory`.\n\n### Immutability\n\nObjects are immutable, so methods on `Config` which transform the\nconfiguration return a new `Config`. Other types such as\n`ConfigParseOptions`, `ConfigResolveOptions`, `ConfigObject`,\netc. are also immutable. See the\n[API docs](https://lightbend.github.io/config/latest/api/) for\ndetails of course.\n\n### Schemas and Validation\n\nThere isn't a schema language or anything like that. However, two\nsuggested tools are:\n\n - use the\n   [checkValid() method](https://lightbend.github.io/config/latest/api/com/typesafe/config/Config.html#checkValid-com.typesafe.config.Config-java.lang.String...-)\n - access your config through a Settings class with a field for\n   each setting, and instantiate it on startup (immediately\n   throwing an exception if any settings are missing)\n\nIn Scala, a Settings class might look like:\n\n    class Settings(config: Config) {\n\n        // validate vs. reference.conf\n        config.checkValid(ConfigFactory.defaultReference(), \"simple-lib\")\n\n        // non-lazy fields, we want all exceptions at construct time\n        val foo = config.getString(\"simple-lib.foo\")\n        val bar = config.getInt(\"simple-lib.bar\")\n    }\n\nSee the examples/ directory for a full compilable program using\nthis pattern.\n\n### Standard behavior\n\nThe convenience method `ConfigFactory.load()` loads the following\n(first-listed are higher priority):\n\n  - system properties\n  - `application.conf` (all resources on classpath with this name)\n  - `application.json` (all resources on classpath with this name)\n  - `application.properties` (all resources on classpath with this\n    name)\n  - `reference.conf` (all resources on classpath with this name)\n\nThe idea is that libraries and frameworks should ship with a\n`reference.conf` in their jar. Applications should provide an\n`application.conf`, or if they want to create multiple\nconfigurations in a single JVM, they could use\n`ConfigFactory.load(\"myapp\")` to load their own `myapp.conf`.\n\nLibraries and frameworks should default to `ConfigFactory.load()`\nif the application does not provide a custom `Config` object. This\nway, libraries will see configuration from `application.conf` and\nusers can configure the whole app, with its libraries, in a single\n`application.conf` file.\n\nLibraries and frameworks should also allow the application to\nprovide a custom `Config` object to be used instead of the\ndefault, in case the application needs multiple configurations in\none JVM or wants to load extra config files from somewhere.  The\nlibrary examples in `examples/` show how to accept a custom config\nwhile defaulting to `ConfigFactory.load()`.\n\nFor applications using `application.{conf,json,properties}`,\nsystem properties can be used to force a different config source\n(e.g. from command line `-Dconfig.file=path/to/config-file`):\n\n - `config.resource` specifies a resource name - not a\n   basename, i.e. `application.conf` not `application`\n - `config.file` specifies a filesystem path, again\n   it should include the extension, not be a basename\n - `config.url` specifies a URL\n\n **Note**: you need to pass `-Dconfig.file=path/to/config-file` before the jar itself, e.g. `java -Dconfig.file=path/to/config-file.conf -jar path/to/jar-file.jar`. Same applies for `-Dconfig.resource=config-file.conf`\n\nThese system properties specify a _replacement_ for\n`application.{conf,json,properties}`, not an addition. They only\naffect apps using the default `ConfigFactory.load()`\nconfiguration. In the replacement config file, you can use\n`include \"application\"` to include the original default config\nfile; after the include statement you could go on to override\ncertain settings.\n\nIf you set `config.resource`, `config.file`, or `config.url`\non-the-fly from inside your program (for example with\n`System.setProperty()`), be aware that `ConfigFactory` has some\ninternal caches and may not see new values for system\nproperties. Use `ConfigFactory.invalidateCaches()` to force-reload\nsystem properties.\n\n#### Note about resolving substitutions in `reference.conf` and `application.conf`\n\nThe substitution syntax `${foo.bar}` will be resolved\ntwice. First, all the `reference.conf` files are merged and then\nthe result gets resolved. Second, all the `application.conf` are\nlayered over the unresolved `reference.conf` and the result of that\ngets resolved again.\n\nThe implication of this is that the `reference.conf` stack has to\nbe self-contained; you can't leave an undefined value `${foo.bar}`\nto be provided by `application.conf`. It is however possible to\noverride a variable that `reference.conf` refers to, as long as\n`reference.conf` also defines that variable itself.\n\n### Merging config trees\n\nAny two Config objects can be merged with an associative operation\ncalled `withFallback`, like `merged = firstConfig.withFallback(secondConfig)`.\n\nThe `withFallback` operation is used inside the library to merge\nduplicate keys in the same file and to merge multiple files.\n`ConfigFactory.load()` uses it to stack system properties over\n`application.conf` over `reference.conf`.\n\nYou can also use `withFallback` to merge in some hardcoded values,\nor to \"lift\" a subtree up to the root of the configuration; say\nyou have something like:\n\n    foo=42\n    dev.foo=57\n    prod.foo=10\n\nThen you could code something like:\n\n    Config devConfig = originalConfig\n                         .getConfig(\"dev\")\n                         .withFallback(originalConfig)\n\nThere are lots of ways to use `withFallback`.\n\n### How to handle defaults\n\nMany other configuration APIs allow you to provide a default to\nthe getter methods, like this:\n\n    boolean getBoolean(String path, boolean fallback)\n\nHere, if the path has no setting, the fallback would be\nreturned. An API could also return `null` for unset values, so you\nwould check for `null`:\n\n    // returns null on unset, check for null and fall back\n    Boolean getBoolean(String path)\n\nThe methods on the `Config` interface do NOT do this, for two\nmajor reasons:\n\n 1. If you use a config setting in two places, the default\n fallback value gets cut-and-pasted and typically out of\n sync. This can result in Very Evil Bugs.\n 2. If the getter returns `null` (or `None`, in Scala) then every\n time you get a setting you have to write handling code for\n `null`/`None` and that code will almost always just throw an\n exception. Perhaps more commonly, people forget to check for\n `null` at all, so missing settings result in\n `NullPointerException`.\n\nFor most situations, failure to have a setting is simply a bug to fix\n(in either code or the deployment environment). Therefore, if a\nsetting is unset, by default the getters on the `Config` interface\nthrow an exception.\n\nIf you want to allow a setting to be missing from\n`application.conf` in a particular case, then here are some\noptions:\n\n 1. Set it in a `reference.conf` included in your library or\n application jar, so there's a default value.\n 2. Use the `Config.hasPath()` method to check in advance whether\n the path exists (rather than checking for `null`/`None` after as\n you might in other APIs).\n 3. Catch and handle `ConfigException.Missing`. NOTE: using an\n exception for control flow like this is much slower than using\n `Config.hasPath()`; the JVM has to do a lot of work to throw\n an exception.\n 4. In your initialization code, generate a `Config` with your\n defaults in it (using something like `ConfigFactory.parseMap()`)\n then fold that default config into your loaded config using\n `withFallback()`, and use the combined config in your\n program. \"Inlining\" your reference config in the code like this\n is probably less convenient than using a `reference.conf` file,\n but there may be reasons to do it.\n 5. Use `Config.root()` to get the `ConfigObject` for the\n `Config`; `ConfigObject` implements `java.util.Map\u003cString,?\u003e` and\n the `get()` method on `Map` returns null for missing keys. See\n the API docs for more detail on `Config` vs. `ConfigObject`.\n 6. Set the setting to `null` in `reference.conf`, then use\n `Config.getIsNull` and `Config.hasPathOrNull` to handle `null`\n in a special way while still throwing an exception if the setting\n is entirely absent.\n\nThe *recommended* path (for most cases, in most apps) is that you\nrequire all settings to be present in either `reference.conf` or\n`application.conf` and allow `ConfigException.Missing` to be\nthrown if they are not. That's the design intent of the `Config`\nAPI design.\n\nConsider the \"Settings class\" pattern with `checkValid()` to\nverify that you have all settings when you initialize the\napp. See the [Schemas and Validation](#schemas-and-validation)\nsection of this README for more details on this pattern.\n\n**If you do need a setting to be optional**: checking `hasPath()` in\nadvance should be the same amount of code (in Java) as checking\nfor `null` afterward, without the risk of `NullPointerException`\nwhen you forget. In Scala, you could write an enrichment class\nlike this to use the idiomatic `Option` syntax:\n\n```scala\nimplicit class RichConfig(val underlying: Config) extends AnyVal {\n  def getOptionalBoolean(path: String): Option[Boolean] = if (underlying.hasPath(path)) {\n     Some(underlying.getBoolean(path))\n  } else {\n     None\n  }\n}\n```\n\nSince this library is a Java library it doesn't come with that out\nof the box, of course.\n\nIt is understood that sometimes defaults in code make sense. For\nexample, if your configuration lets users invent new sections, you\nmay not have all paths up front and may be unable to set up\ndefaults in `reference.conf` for dynamic paths. The design intent\nof `Config` isn't to *prohibit* inline defaults, but simply to\nrecognize that it seems to be the 10% case (rather than the 90%\ncase). Even in cases where dynamic defaults are needed, you may\nfind that using `withFallback()` to build a complete\nnothing-missing `Config` in one central place in your code keeps\nthings tidy.\n\nWhatever you do, please remember not to cut-and-paste default\nvalues into multiple places in your code. You have been warned!\n:-)\n\n### Understanding `Config` and `ConfigObject`\n\nTo read and modify configuration, you'll use the\n[Config](https://lightbend.github.io/config/latest/api/com/typesafe/config/Config.html)\ninterface. A `Config` looks at a JSON-equivalent data structure as\na one-level map from paths to values. So if your JSON looks like\nthis:\n\n```\n  \"foo\" : {\n    \"bar\" : 42\n    \"baz\" : 43\n  }\n```\n\nUsing the `Config` interface, you could write\n`conf.getInt(\"foo.bar\")`. The `foo.bar` string is called a _path\nexpression_\n([HOCON.md](https://github.com/lightbend/config/blob/main/HOCON.md)\nhas the syntax details for these expressions). Iterating over this\n`Config`, you would get two entries; `\"foo.bar\" : 42` and\n`\"foo.baz\" : 43`. When iterating a `Config` you will not find\nnested `Config` (because everything gets flattened into one\nlevel).\n\nWhen looking at a JSON tree as a `Config`, `null` values are\ntreated as if they were missing. Iterating over a `Config` will\nskip `null` values.\n\nYou can also look at a `Config` in the way most JSON APIs would,\nthrough the\n[ConfigObject](https://lightbend.github.io/config/latest/api/com/typesafe/config/ConfigObject.html)\ninterface. This interface represents an object node in the JSON\ntree. `ConfigObject` instances come in multi-level trees, and the\nkeys do not have any syntax (they are just strings, not path\nexpressions). Iterating over the above example as a\n`ConfigObject`, you would get one entry `\"foo\" : { \"bar\" : 42,\n\"baz\" : 43 }`, where the value at `\"foo\"` is another nested\n`ConfigObject`.\n\nIn `ConfigObject`, `null` values are visible (distinct from\nmissing values), just as they are in JSON.\n\n`ConfigObject` is a subtype of [ConfigValue](https://lightbend.github.io/config/latest/api/com/typesafe/config/ConfigValue.html), where the other\nsubtypes are the other JSON types (list, string, number, boolean, null).\n\n`Config` and `ConfigObject` are two ways to look at the same\ninternal data structure, and you can convert between them for free\nusing\n[Config.root()](https://lightbend.github.io/config/latest/api/com/typesafe/config/Config.html#root--)\nand\n[ConfigObject.toConfig()](https://lightbend.github.io/config/latest/api/com/typesafe/config/ConfigObject.html#toConfig--).\n\n### ConfigBeanFactory\n\nAs of version 1.3.0, if you have a Java object that follows\nJavaBean conventions (zero-args constructor, getters and setters),\nyou can automatically initialize it from a `Config`.\n\nUse\n`ConfigBeanFactory.create(config.getConfig(\"subtree-that-matches-bean\"),\nMyBean.class)` to do this.\n\nCreating a bean from a `Config` automatically validates that the\nconfig matches the bean's implied schema. Bean fields can be\nprimitive types, typed lists such as `List\u003cInteger\u003e`,\n`java.time.Duration`, `ConfigMemorySize`, or even a raw `Config`,\n`ConfigObject`, or `ConfigValue` (if you'd like to deal with a\nparticular value manually).\n\n## Using HOCON, the JSON Superset\n\nThe JSON superset is called \"Human-Optimized Config Object\nNotation\" or HOCON, and files use the suffix `.conf`.  See\n[HOCON.md](https://github.com/lightbend/config/blob/main/HOCON.md)\nin this directory for more detail.\n\nAfter processing a `.conf` file, the result is always just a JSON\ntree that you could have written (less conveniently) in JSON.\n\n### Features of HOCON\n\n  - Comments, with `#` or `//`\n  - Allow omitting the `{}` around a root object\n  - Allow `=` as a synonym for `:`\n  - Allow omitting the `=` or `:` before a `{` so\n    `foo { a : 42 }`\n  - Allow omitting commas as long as there's a newline\n  - Allow trailing commas after last element in objects and arrays\n  - Allow unquoted strings for keys and values\n  - Unquoted keys can use dot-notation for nested objects,\n    `foo.bar=42` means `foo { bar : 42 }`\n  - Duplicate keys are allowed; later values override earlier,\n    except for object-valued keys where the two objects are merged\n    recursively\n  - `include` feature merges root object in another file into\n    current object, so `foo { include \"bar.json\" }` merges keys in\n    `bar.json` into the object `foo`\n  - include with no file extension includes any of `.conf`,\n    `.json`, `.properties`\n  - you can include files, URLs, or classpath resources; use\n    `include url(\"http://example.com\")` or `file()` or\n    `classpath()` syntax to force the type, or use just `include\n    \"whatever\"` to have the library do what you probably mean\n    (Note: `url()`/`file()`/`classpath()` syntax is not supported\n    in Play/Akka 2.0, only in later releases.)\n  - substitutions `foo : ${a.b}` sets key `foo` to the same value\n    as the `b` field in the `a` object\n  - substitutions concatenate into unquoted strings, `foo : the\n    quick ${colors.fox} jumped`\n  - substitutions fall back to environment variables if they don't\n    resolve in the config itself, so `${HOME}` would work as you\n    expect. Also, most configs have system properties merged in so\n    you could use `${user.home}`.\n  - substitutions normally cause an error if unresolved, but\n    there is a syntax `${?a.b}` to permit them to be missing.\n  - `+=` syntax to append elements to arrays, `path += \"/bin\"`\n  - multi-line strings with triple quotes as in Python or Scala\n\n### Examples of HOCON\n\nAll of these are valid HOCON.\n\nStart with valid JSON:\n\n    {\n        \"foo\" : {\n            \"bar\" : 10,\n            \"baz\" : 12\n        }\n    }\n\nDrop root braces:\n\n    \"foo\" : {\n        \"bar\" : 10,\n        \"baz\" : 12\n    }\n\nDrop quotes:\n\n    foo : {\n        bar : 10,\n        baz : 12\n    }\n\nUse `=` and omit it before `{`:\n\n    foo {\n        bar = 10,\n        baz = 12\n    }\n\nRemove commas:\n\n    foo {\n        bar = 10\n        baz = 12\n    }\n\nUse dotted notation for unquoted keys:\n\n    foo.bar=10\n    foo.baz=12\n\nPut the dotted-notation fields on a single line:\n\n    foo.bar=10, foo.baz=12\n\nThe syntax is well-defined (including handling of whitespace and\nescaping). But it handles many reasonable ways you might want to\nformat the file.\n\nNote that while you can write HOCON that looks a lot like a Java\nproperties file (and many properties files will parse as HOCON),\nthe details of escaping, whitespace handling, comments, and so\nforth are more like JSON. The spec (see HOCON.md in this\ndirectory) has some more detailed notes on this topic.\n\n### Uses of Substitutions\n\nThe `${foo.bar}` substitution feature lets you avoid cut-and-paste\nin some nice ways.\n\n#### Factor out common values\n\nThis is the obvious use,\n\n    standard-timeout = 10ms\n    foo.timeout = ${standard-timeout}\n    bar.timeout = ${standard-timeout}\n\n#### Inheritance\n\nIf you duplicate a field with an object value, then the objects\nare merged with last-one-wins. So:\n\n    foo = { a : 42, c : 5 }\n    foo = { b : 43, c : 6 }\n\nmeans the same as:\n\n    foo = { a : 42, b : 43, c : 6 }\n\nYou can take advantage of this for \"inheritance\":\n\n    data-center-generic = { cluster-size = 6 }\n    data-center-east = ${data-center-generic}\n    data-center-east = { name = \"east\" }\n    data-center-west = ${data-center-generic}\n    data-center-west = { name = \"west\", cluster-size = 8 }\n\nUsing `include` statements you could split this across multiple\nfiles, too.\n\nIf you put two objects next to each other (close brace of the first\non the same line with open brace of the second), they are merged, so\na shorter way to write the above \"inheritance\" example would be:\n\n    data-center-generic = { cluster-size = 6 }\n    data-center-east = ${data-center-generic} { name = \"east\" }\n    data-center-west = ${data-center-generic} { name = \"west\", cluster-size = 8 }\n\n#### Optional system or env variable overrides\n\nIn default uses of the library, exact-match system properties\nalready override the corresponding config properties.  However,\nyou can add your own overrides, or allow environment variables to\noverride, using the `${?foo}` substitution syntax.\n\n    basedir = \"/whatever/whatever\"\n    basedir = ${?FORCED_BASEDIR}\n\nHere, the override field `basedir = ${?FORCED_BASEDIR}` simply\nvanishes if there's no value for `FORCED_BASEDIR`, but if you set\nan environment variable `FORCED_BASEDIR` for example, it would be\nused.\n\nA natural extension of this idea is to support several different\nenvironment variable names or system property names, if you aren't\nsure which one will exist in the target environment.\n\nObject fields and array elements with a `${?foo}` substitution\nvalue just disappear if the substitution is not found:\n\n    // this array could have one or two elements\n    path = [ \"a\", ${?OPTIONAL_A} ]\n\nBy setting the JVM property `-Dconfig.override_with_env_vars=true`\nit is possible to override any configuration value using environment\nvariables even if an explicit substitution is not specified.\n\nThe environment variable value will override any pre-existing value\nand also any value provided as Java property.\n\nWith this option enabled only environment variables starting with\n`CONFIG_FORCE_` are considered, and the name is mangled as follows:\n\n  - the prefix `CONFIG_FORCE_` is stripped\n  - single underscore(`_`) is converted into a dot(`.`)\n  - double underscore(`__`) is converted into a dash(`-`)\n  - triple underscore(`___`) is converted into a single underscore(`_`)\n\ni.e. The environment variable `CONFIG_FORCE_a_b__c___d` set the\nconfiguration key `a.b-c_d`\n\n### Set array values outside configuration files\n\nSetting the value of array items from java properties or environment\nvariables require specifying the index in the array for the value.\nSo, while in HOCON you can set multiple values into an array or\nappend to an array:\n\n    ## HOCON\n    items = [\"a\", \"b\"]\n    items += \"c\"\n\nUsing java properties you specify the exact position:\n\n    -Ditems.0=\"a\" -Ditems.1=\"b\"\n\nas well as with environment variables:\n\n    export CONFIG_FORCE_items_0=a\n    export CONFIG_FORCE_items_1=b\n\n### Concatenation\n\nValues _on the same line_ are concatenated (for strings and\narrays) or merged (for objects).\n\nThis is why unquoted strings work, here the number `42` and the\nstring `foo` are concatenated into a string `42 foo`:\n\n    key : 42 foo\n\nWhen concatenating values into a string, leading and trailing\nwhitespace is stripped but whitespace between values is kept.\n\nQuoted or unquoted strings can also concatenate with substitutions of course:\n\n    tasks-url : ${base-url}/tasks\n    tasks-url : ${base-url}\"tasks:colon-must-be-quoted\"\n\nNote: the `${}` syntax must be outside the quotes!\n\nA concatenation can refer to earlier values of the same field:\n\n    path : \"/bin\"\n    path : ${path}\":/usr/bin\"\n\nArrays can be concatenated as well:\n\n    path : [ \"/bin\" ]\n    path : ${path} [ \"/usr/bin\" ]\n\nThere is a shorthand for appending to arrays:\n\n    // equivalent to: path = ${?path} [ \"/usr/bin\" ]\n    path += \"/usr/bin\"\n\nTo prepend or insert into an array, there is no shorthand.\n\nWhen objects are \"concatenated,\" they are merged, so object\nconcatenation is just a shorthand for defining the same object\ntwice. The long way (mentioned earlier) is:\n\n    data-center-generic = { cluster-size = 6 }\n    data-center-east = ${data-center-generic}\n    data-center-east = { name = \"east\" }\n\nThe concatenation-style shortcut is:\n\n    data-center-generic = { cluster-size = 6 }\n    data-center-east = ${data-center-generic} { name = \"east\" }\n\nWhen concatenating objects and arrays, newlines are allowed\n_inside_ each object or array, but not between them.\n\nNon-newline whitespace is never a field or element separator. So\n`[ 1 2 3 4 ]` is an array with one unquoted string element\n`\"1 2 3 4\"`. To get an array of four numbers you need either commas or\nnewlines separating the numbers.\n\nSee the spec for full details on concatenation.\n\nNote: Play/Akka 2.0 have an earlier version that supports string\nconcatenation, but not object/array concatenation. `+=` does not\nwork in Play/Akka 2.0 either. Post-2.0 versions support these\nfeatures.\n\n## Miscellaneous Notes\n\n### Debugging Your Configuration\n\nIf you have trouble with your configuration, some useful tips.\n\n - Set the Java system property `-Dconfig.trace=loads` to get\n   output on stderr describing each file that is loaded.\n   Note: this feature is not included in the older version in\n   Play/Akka 2.0.\n - Use `myConfig.root().render()` to get a `Config` as a\n   string with comments showing where each value came from.\n   This string can be printed out on console or logged to \n   a file etc.\n - If you see errors like\n   `com.typesafe.config.ConfigException$Missing: No configuration setting found for key foo`,\n   and you're sure that key is defined in your config file, they might appear e.g.\n   when you're loading configuration from a thread that's not the JVM's main thread.\n   Try passing the `ClassLoader` in manually - e.g. with `ConfigFactory.load(getClass().getClassLoader())`\n   or setting the context class loader.\n   If you don't pass one, Lightbend Config uses the calling thread's `contextClassLoader`, and in some cases,\n   it may not have your configuration files in its classpath,\n   so loading the config on that thread can yield unexpected, erroneous results.\n\n### Supports Java 8 and Later\n\nCurrently the library is maintained against Java 8, but\nversion 1.2.1 and earlier will work with Java 6.\n\nPlease use 1.2.1 if you need Java 6 support, though some people\nhave expressed interest in a branch off of 1.3.x supporting\nJava 7. If you want to work on that branch you might bring it up\non [chat](https://gitter.im/lightbend/config). We can release a\njar for Java 7 if someone(s) steps up to maintain the branch. The\nmain branch does not use Java 8 \"gratuitously\" but some APIs\nthat use Java 8 types will need to be removed.\n\n### Rationale for Supported File Formats\n\n(For the curious.)\n\nThe three file formats each have advantages.\n\n - Java `.properties`:\n   - Java standard, built in to JVM\n   - Supported by many tools such as IDEs\n - JSON:\n   - easy to generate programmatically\n   - well-defined and standard\n   - bad for human maintenance, with no way to write comments,\n     and no mechanisms to avoid duplication of similar config\n     sections\n - HOCON/`.conf`:\n   - nice for humans to read, type, and maintain, with more\n     lenient syntax\n   - built-in tools to avoid cut-and-paste\n   - ways to refer to the system environment, such as system\n     properties and environment variables\n\nThe idea would be to use JSON if you're writing a script to spit\nout config, and use HOCON if you're maintaining config by hand.\nIf you're doing both, then mix the two.\n\nTwo alternatives to HOCON syntax could be:\n\n  - YAML is also a JSON superset and has a mechanism for adding\n    custom types, so the include statements in HOCON could become\n    a custom type tag like `!include`, and substitutions in HOCON\n    could become a custom tag such as `!subst`, for example. The\n    result is somewhat clunky to write, but would have the same\n    in-memory representation as the HOCON approach.\n  - Put a syntax inside JSON strings, so you might write something\n    like `\"$include\" : \"filename\"` or allow `\"foo\" : \"${bar}\"`.\n    This is a way to tunnel new syntax through a JSON parser, but\n    other than the implementation benefit (using a standard JSON\n    parser), it doesn't really work. It's a bad syntax for human\n    maintenance, and it's not valid JSON anymore because properly\n    interpreting it requires treating some valid JSON strings as\n    something other than plain strings. A better approach is to\n    allow mixing true JSON files into the config but also support\n    a nicer format.\n\n### Other APIs (Wrappers, Ports and Utilities)\n\nThis may not be comprehensive - if you'd like to add mention of\nyour wrapper, just send a pull request for this README. We would\nlove to know what you're doing with this library or with the HOCON\nformat.\n\n#### Guice integration\n  * Typesafe Config Guice https://github.com/racc/typesafeconfig-guice\n\n#### Java (yep!) wrappers for the Java library\n\n  * tscfg https://github.com/carueda/tscfg\n\n#### Scala wrappers for the Java library\n\n  * Ficus https://github.com/iheartradio/ficus\n  * configz https://github.com/arosien/configz\n  * configs https://github.com/kxbmap/configs\n  * config-annotation https://github.com/zhongl/config-annotation\n  * PureConfig https://github.com/pureconfig/pureconfig\n  * Simple Scala Config https://github.com/ElderResearch/ssc\n  * konfig https://github.com/vpon/konfig\n  * ScalaConfig https://github.com/andr83/scalaconfig\n  * static-config https://github.com/Krever/static-config\n  * validated-config https://github.com/carlpulley/validated-config\n  * Cedi Config https://github.com/ccadllc/cedi-config\n  * Cfg https://github.com/carueda/cfg\n  * circe-config https://github.com/circe/circe-config\n  * args4c https://github.com/aaronp/args4c\n\n#### Clojure wrappers for the Java library\n\n  * beamly-core.config https://github.com/beamly/beamly-core.config\n\n#### Kotlin wrappers for the Java library\n\n  * config4k https://github.com/config4k/config4k\n  * hoplite https://github.com/sksamuel/hoplite\n\n#### Scala port\n\n  * SHocon https://github.com/akka-js/shocon (Supports Scala.js and Scala Native)\n  * sconfig https://github.com/ekrich/sconfig (Supports JVM, Scala Native, and Scala.js)\n\n#### Ruby port\n\n   * https://github.com/puppetlabs/ruby-hocon\n\n#### Puppet module\n\n   * Manage your HOCON configuration files with Puppet!: https://forge.puppetlabs.com/puppetlabs/hocon\n\n#### Python port\n\n   * pyhocon https://github.com/chimpler/pyhocon\n\n#### C++ port\n\n   * https://github.com/puppetlabs/cpp-hocon\n\n#### JavaScript port\n\n  * https://github.com/yellowblood/hocon-js (missing features, under development)\n\n#### C# port\n\n  * https://github.com/akkadotnet/HOCON\n\n#### Rust port\n\n  * https://github.com/mockersf/hocon.rs (unmaintained)\n  * https://github.com/mikai233/hocon-rs\n\n#### Go port\n\n  * https://github.com/gurkankaymak/hocon\n \n#### Erlang port\n  * https://github.com/emqx/hocon\n\n#### Linting tool\n\n   * A web based linting tool http://www.hoconlint.com/\n\n#### Online playground\n\n   * https://hocon-playground.tehbrian.dev\n\n# Maintenance notes\n\n## License\n\nThe license is Apache 2.0, see LICENSE-2.0.txt.\n\n## Maintained by \n\nThe \"Typesafe Config\" library is an important foundation to how Akka and other JVM libraries manage configuration. We at [Lightbend](https://lightbend.com) consider the functionality of this library as feature complete. We will make sure \"Typesafe Config\" keeps up with future JVM versions, but will rarely make any other changes.\n\nWe are thankful for all the work [@havocp](https://github.com/havocp) has put into creating the library initially and supporting its users over many more years, even after leaving Lightbend.\n","funding_links":[],"categories":["第三方库介绍","Java","Projects","项目","Solutions"],"sub_categories":["配置文件","Configuration","配置"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flightbend%2Fconfig","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flightbend%2Fconfig","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flightbend%2Fconfig/lists"}