{"id":13498277,"url":"https://github.com/uchuhimo/konf","last_synced_at":"2025-04-05T06:09:55.456Z","repository":{"id":47350100,"uuid":"96800312","full_name":"uchuhimo/konf","owner":"uchuhimo","description":"A type-safe cascading configuration library for Kotlin/Java/Android, supporting most configuration formats","archived":false,"fork":false,"pushed_at":"2023-05-17T22:38:38.000Z","size":1482,"stargazers_count":309,"open_issues_count":13,"forks_count":28,"subscribers_count":10,"default_branch":"master","last_synced_at":"2024-10-19T05:16:59.376Z","etag":null,"topics":["android","config","configuration","git","hocon","java","javascript","json","konf","kotlin","properties","toml","xml","yaml"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/uchuhimo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2017-07-10T16:47:17.000Z","updated_at":"2024-10-08T13:58:39.000Z","dependencies_parsed_at":"2024-01-18T23:04:45.754Z","dependency_job_id":"e817e246-2dc2-44ed-a3f2-3e93afffcd5c","html_url":"https://github.com/uchuhimo/konf","commit_stats":null,"previous_names":[],"tags_count":34,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uchuhimo%2Fkonf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uchuhimo%2Fkonf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uchuhimo%2Fkonf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uchuhimo%2Fkonf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/uchuhimo","download_url":"https://codeload.github.com/uchuhimo/konf/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247294541,"owners_count":20915340,"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":["android","config","configuration","git","hocon","java","javascript","json","konf","kotlin","properties","toml","xml","yaml"],"created_at":"2024-07-31T21:00:21.287Z","updated_at":"2025-04-05T06:09:55.435Z","avatar_url":"https://github.com/uchuhimo.png","language":"Kotlin","funding_links":[],"categories":["Uncategorized"],"sub_categories":["Uncategorized"],"readme":"# Konf\n\n[![Java 8+](https://img.shields.io/badge/Java-8+-4c7e9f.svg)](http://java.oracle.com)\n[![Maven metadata URL](https://img.shields.io/maven-central/v/com.uchuhimo/konf)](https://search.maven.org/artifact/com.uchuhimo/konf)\n[![JitPack](https://img.shields.io/jitpack/v/github/uchuhimo/konf)](https://jitpack.io/#uchuhimo/konf)\n[![Build Status](https://travis-ci.org/uchuhimo/konf.svg?branch=master)](https://travis-ci.org/uchuhimo/konf)\n[![codecov](https://codecov.io/gh/uchuhimo/konf/branch/master/graph/badge.svg)](https://codecov.io/gh/uchuhimo/konf)\n[![codebeat badge](https://codebeat.co/badges/f69a1574-9d4c-4da5-be73-56fa7b180d2d)](https://codebeat.co/projects/github-com-uchuhimo-konf-master)\n[![Awesome Kotlin Badge](https://kotlin.link/awesome-kotlin.svg)](https://github.com/KotlinBy/awesome-kotlin)\n\nA type-safe cascading configuration library for Kotlin/Java/Android, supporting most configuration formats.\n\n## Features\n\n- **Type-safe**. Get/set value in config with type-safe APIs.\n- **Thread-safe**. All APIs for config is thread-safe.\n- **Batteries included**. Support sources from JSON, XML, YAML, [HOCON](https://github.com/typesafehub/config/blob/master/HOCON.md), [TOML](https://github.com/toml-lang/toml), properties, map, command line and system environment out of box.\n- **Cascading**. Config can fork from another config by adding a new layer on it. Each layer of config can be updated independently. This feature is powerful enough to support complicated situation such as configs with different values share common fallback config, which is automatically updated when configuration file changes.\n- **Self-documenting**. Document config item with type, default value and description when declaring.\n- **Extensible**. Easy to customize new sources for config or expose items in config.\n\n## Contents\n\n- [Konf](#konf)\n  - [Features](#features)\n  - [Contents](#contents)\n  - [Prerequisites](#prerequisites)\n  - [Use in your projects](#use-in-your-projects)\n    - [Maven](#maven)\n    - [Gradle](#gradle)\n    - [Gradle Kotlin DSL](#gradle-kotlin-dsl)\n    - [Maven (master snapshot)](#maven-master-snapshot)\n    - [Gradle (master snapshot)](#gradle-master-snapshot)\n    - [Gradle Kotlin DSL (master snapshot)](#gradle-kotlin-dsl-master-snapshot)\n  - [Quick start](#quick-start)\n  - [Define items](#define-items)\n  - [Use config](#use-config)\n    - [Create config](#create-config)\n    - [Add config spec](#add-config-spec)\n    - [Retrieve value from config](#retrieve-value-from-config)\n    - [Cast config to value](#cast-config-to-value)\n    - [Check whether an item exists in config or not](#check-whether-an-item-exists-in-config-or-not)\n    - [Modify value in config](#modify-value-in-config)\n    - [Subscribe the update event](#subscribe-the-update-event)\n    - [Export value in config as property](#export-value-in-config-as-property)\n    - [Fork from another config](#fork-from-another-config)\n  - [Load values from source](#load-values-from-source)\n    - [Subscribe the update event for load operation](#subscribe-the-update-event-for-load-operation)\n    - [Strict parsing when loading](#strict-parsing-when-loading)\n    - [Path substitution](#path-substitution)\n  - [Prefix/Merge operations for source/config/config spec](#prefixmerge-operations-for-sourceconfigconfig-spec)\n  - [Export/Reload values in config](#exportreload-values-in-config)\n  - [Supported item types](#supported-item-types)\n  - [Optional features](#optional-features)\n  - [Build from source](#build-from-source)\n  - [Breaking Changes](#breaking-changes)\n    - [v0.19.0](#v0190)\n    - [v0.17.0](#v0170)\n    - [v0.15](#v015)\n    - [v0.10](#v010)\n- [License](#license)\n\n## Prerequisites\n\n- JDK 8 or higher\n- tested on Android SDK 23 or higher\n\n## Use in your projects\n\nThis library has been published to [Maven Central](https://search.maven.org/artifact/com.uchuhimo/konf) and [JitPack](https://jitpack.io/#uchuhimo/konf).\n\nKonf is modular, you can use different modules for different sources:\n\n- `konf-core`: for built-in sources (JSON, properties, map, command line and system environment)\n- `konf-hocon`: for built-in + [HOCON](https://github.com/typesafehub/config/blob/master/HOCON.md) sources\n- `konf-toml`: for built-in + [TOML](https://github.com/toml-lang/toml) sources\n- `konf-xml`: for built-in + XML sources\n- `konf-yaml`: for built-in + YAML sources\n- `konf-git`: for built-in + Git sources\n- `konf`: for all sources mentioned above\n- `konf-js`: for built-in + JavaScript (use GraalVM JavaScript) sources\n\n### Maven\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.uchuhimo\u003c/groupId\u003e\n  \u003cartifactId\u003ekonf\u003c/artifactId\u003e\n  \u003cversion\u003e1.1.2\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n### Gradle\n\n```groovy\ncompile 'com.uchuhimo:konf:1.1.2'\n```\n\n### Gradle Kotlin DSL\n\n```kotlin\ncompile(group = \"com.uchuhimo\", name = \"konf\", version = \"1.1.2\")\n```\n\n### Maven (master snapshot)\n\nAdd JitPack repository to `\u003crepositories\u003e` section:\n\n```xml\n\u003crepository\u003e\n    \u003cid\u003ejitpack.io\u003c/id\u003e\n    \u003curl\u003ehttps://jitpack.io\u003c/url\u003e\n\u003c/repository\u003e\n```\n\nAdd dependencies:\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.github.uchuhimo\u003c/groupId\u003e\n    \u003cartifactId\u003ekonf\u003c/artifactId\u003e\n    \u003cversion\u003emaster-SNAPSHOT\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n### Gradle (master snapshot)\n\nAdd JitPack repository:\n\n```groovy\nrepositories {\n    maven { url 'https://jitpack.io' }\n}\n```\n\nAdd dependencies:\n\n```groovy\ncompile 'com.github.uchuhimo.konf:konf:master-SNAPSHOT'\n```\n\n### Gradle Kotlin DSL (master snapshot)\n\nAdd JitPack repository:\n\n```kotlin\nrepositories {\n    maven(url = \"https://jitpack.io\")\n}\n```\n\nAdd dependencies:\n\n```kotlin\ncompile(group = \"com.github.uchuhimo.konf\", name = \"konf\", version = \"master-SNAPSHOT\")\n```\n\n## Quick start\n\n1. Define items in config spec:\n\n    ```kotlin\n    object ServerSpec : ConfigSpec() {\n        val host by optional(\"0.0.0.0\")\n        val tcpPort by required\u003cInt\u003e()\n    }\n    ```\n\n2. Construct config with items in config spec and values from multiple sources:\n\n    ```kotlin\n    val config = Config { addSpec(ServerSpec) }\n            .from.yaml.file(\"server.yml\")\n            .from.json.resource(\"server.json\")\n            .from.env()\n            .from.systemProperties()\n    ```\n   \n   or:\n\n    ```kotlin\n    val config = Config { addSpec(ServerSpec) }.withSource(\n        Source.from.yaml.file(\"server.yml\") +\n        Source.from.json.resource(\"server.json\") +\n        Source.from.env() +\n        Source.from.systemProperties()\n    )\n    ```\n\n    This config contains all items defined in `ServerSpec`, and load values from 4 different sources. Values in resource file `server.json` will override those in file `server.yml`, values from system environment will override those in `server.json`, and values from system properties will override those from system environment.\n\n    If you want to watch file `server.yml` and reload values when file content is changed, you can use `watchFile` instead of `file`:\n\n    ```kotlin\n    val config = Config { addSpec(ServerSpec) }\n            .from.yaml.watchFile(\"server.yml\")\n            .from.json.resource(\"server.json\")\n            .from.env()\n            .from.systemProperties()\n    ```\n\n3. Define values in source. You can define in any of these sources:\n    - in `server.yml`:\n        ```yaml\n        server:\n            host: 0.0.0.0\n            tcp_port: 8080\n        ```\n    - in `server.json`:\n        ```json\n        {\n            \"server\": {\n                \"host\": \"0.0.0.0\",\n                \"tcp_port\": 8080\n            }\n        }\n        ```\n    - in system environment:\n        ```bash\n        SERVER_HOST=0.0.0.0\n        SERVER_TCPPORT=8080\n        ```\n    - in command line for system properties:\n        ```bash\n        -Dserver.host=0.0.0.0 -Dserver.tcp_port=8080\n        ```\n\n4. Retrieve values from config with type-safe APIs:\n    ```kotlin\n    data class Server(val host: String, val tcpPort: Int) {\n        fun start() {}\n    }\n    \n    val server = Server(config[ServerSpec.host], config[ServerSpec.tcpPort])\n    server.start()\n    ```\n\n5. Retrieve values from multiple sources without using config spec:\n\n    ```kotlin\n    val server = Config()\n            .from.yaml.file(\"server.yml\")\n            .from.json.resource(\"server.json\")\n            .from.env()\n            .from.systemProperties()\n            .at(\"server\")\n            .toValue\u003cServer\u003e()\n    server.start()\n    ```\n\n## Define items\n\nConfig items is declared in config spec, added to config by `Config#addSpec`. All items in same config spec have same prefix. Define a config spec with prefix `local.server`:\n\n```kotlin\nobject ServerSpec : ConfigSpec(\"server\") {\n}\n```\n\nIf the config spec is binding with single class, you can declare config spec as companion object of the class:\n\n```kotlin\nclass Server {\n    companion object : ConfigSpec(\"server\") {\n        val host by optional(\"0.0.0.0\")\n        val tcpPort by required\u003cInt\u003e()\n    }\n}\n```\n\nThe config spec prefix can be automatically inferred from the class name, leading to further simplification like:\n\n```kotlin\nobject ServerSpec : ConfigSpec() {\n}\n```\n\nor\n\n```kotlin\nclass Server {\n    companion object : ConfigSpec() {\n    }\n}\n```\n\nHere are some examples showing the inference convention: `Uppercase` to `uppercase`, `lowercase` to `lowercase`, `SuffixSpec` to `suffix`, `TCPService` to `tcpService`.\n\nThe config spec can also be nested. For example, the path of `Service.Backend.Login.user` in the following example will be inferred as \"service.backend.login.user\":\n\n```kotlin\nobject Service : ConfigSpec() {\n    object Backend : ConfigSpec() {\n        object Login : ConfigSpec() {\n            val user by optional(\"admin\")\n        }\n    }\n}\n```\n\nThere are three kinds of item:\n\n- Required item. Required item doesn't have default value, thus must be set with value before retrieved in config. Define a required item with description:\n    ```kotlin\n    val tcpPort by required\u003cInt\u003e(description = \"port of server\")\n    ```\n    Or omit the description:\n    ```kotlin\n    val tcpPort by required\u003cInt\u003e()\n    ```\n- Optional item. Optional item has default value, thus can be safely retrieved before setting. Define an optional item:\n    ```kotlin\n    val host by optional(\"0.0.0.0\", description = \"host IP of server\")\n    ```\n    Description can be omitted.\n- Lazy item. Lazy item also has default value, however, the default value is not a constant, it is evaluated from thunk every time when retrieved. Define a lazy item:\n    ```kotlin\n    val nextPort by lazy { config -\u003e config[tcpPort] + 1 }\n    ```\n\nYou can also define config spec in Java, with a more verbose API (compared to Kotlin version in \"quick start\"):\n\n```java\npublic class ServerSpec {\n  public static final ConfigSpec spec = new ConfigSpec(\"server\");\n\n  public static final OptionalItem\u003cString\u003e host =\n      new OptionalItem\u003cString\u003e(spec, \"host\", \"0.0.0.0\") {};\n\n  public static final RequiredItem\u003cInteger\u003e tcpPort = new RequiredItem\u003cInteger\u003e(spec, \"tcpPort\") {};\n}\n```\n\nNotice that the `{}` part in item declaration is necessary to avoid type erasure of item's type information.\n\n## Use config\n\n### Create config\n\nCreate an empty new config:\n\n```kotlin\nval config = Config()\n```\n\nOr an new config with some initial actions:\n\n```kotlin\nval config = Config { addSpec(Server) }\n```\n\n### Add config spec\n\nAdd multiple config specs into config:\n\n```kotlin\nconfig.addSpec(Server)\nconfig.addSpec(Client)\n```\n\n### Retrieve value from config\n\nRetrieve associated value with item (type-safe API):\n\n```kotlin\nval host = config[Server.host]\n```\n\nRetrieve associated value with item name (unsafe API):\n\n```kotlin\nval host = config.get\u003cString\u003e(\"server.host\")\n```\n\nor:\n\n```kotlin\nval host = config\u003cString\u003e(\"server.host\")\n```\n\n### Cast config to value\n\nCast config to a value with the target type:\n\n```kotlin\nval server = config.toValue\u003cServer\u003e()\n```\n\n### Check whether an item exists in config or not\n\nCheck whether an item exists in config or not:\n\n```kotlin\nconfig.contains(Server.host)\n// or\nServer.host in config\n```\n\nCheck whether an item name exists in config or not:\n\n```kotlin\nconfig.contains(\"server.host\")\n// or\n\"server.host\" in config\n```\n\nCheck whether all values of required items exist in config or not:\n\n```kotlin\nconfig.containsRequired()\n```\n\nThrow exception if some required items in config don't have values:\n\n```kotlin\nconfig.validateRequired()\n```\n\n### Modify value in config\n\nAssociate item with value (type-safe API):\n\n```kotlin\nconfig[Server.tcpPort] = 80\n```\n\nFind item with specified name, and associate it with value (unsafe API):\n\n```kotlin\nconfig[\"server.tcpPort\"] = 80\n```\n\nDiscard associated value of item:\n\n```kotlin\nconfig.unset(Server.tcpPort)\n```\n\nDiscard associated value of item with specified name:\n\n```kotlin\nconfig.unset(\"server.tcpPort\")\n```\n\nAssociate item with lazy thunk (type-safe API):\n\n```kotlin\nconfig.lazySet(Server.tcpPort) { it[basePort] + 1 }\n```\n\nFind item with specified name, and associate it with lazy thunk (unsafe API):\n\n```kotlin\nconfig.lazySet(\"server.tcpPort\") { it[basePort] + 1 }\n```\n\n### Subscribe the update event\n\nSubscribe the update event of an item:\n\n```kotlin\nval handler = Server.host.onSet { value -\u003e println(\"the host has changed to $value\") }\n```\n\nSubscribe the update event before every set operation:\n\n```kotlin\nval handler = Server.host.beforeSet { config, value -\u003e println(\"the host will change to $value\") }\n```\n\nor\n\n```kotlin\nval handler = config.beforeSet { item, value -\u003e println(\"${item.name} will change to $value\") }\n```\n\nSubscribe the update event after every set operation:\n\n```kotlin\nval handler = Server.host.afterSet { config, value -\u003e println(\"the host has changed to $value\") }\n```\n\nor\n\n```kotlin\nval handler = config.afterSet { item, value -\u003e println(\"${item.name} has changed to $value\") }\n```\n\nCancel the subscription:\n\n```kotlin\nhandler.cancel()\n```\n\n### Export value in config as property\n\nExport a read-write property from value in config:\n\n```kotlin\nvar port by config.property(Server.tcpPort)\nport = 9090\ncheck(port == 9090)\n```\n\nExport a read-only property from value in config:\n\n```kotlin\nval port by config.property(Server.tcpPort)\ncheck(port == 9090)\n```\n\n### Fork from another config\n\n```kotlin\nval config = Config { addSpec(Server) }\nconfig[Server.tcpPort] = 1000\n// fork from parent config\nval childConfig = config.withLayer(\"child\")\n// child config inherit values from parent config\ncheck(childConfig[Server.tcpPort] == 1000)\n// modifications in parent config affect values in child config\nconfig[Server.tcpPort] = 2000\ncheck(config[Server.tcpPort] == 2000)\ncheck(childConfig[Server.tcpPort] == 2000)\n// modifications in child config don't affect values in parent config\nchildConfig[Server.tcpPort] = 3000\ncheck(config[Server.tcpPort] == 2000)\ncheck(childConfig[Server.tcpPort] == 3000)\n```\n\n## Load values from source\n\nUse `from` to load values from source doesn't affect values in config, it will return a new child config by loading all values into new layer in child config:\n\n```kotlin\nval config = Config { addSpec(Server) }\n// values in source is loaded into new layer in child config\nval childConfig = config.from.env()\ncheck(childConfig.parent === config)\n```\n\nAll out-of-box supported sources are declared in [`DefaultLoaders`](https://github.com/uchuhimo/konf/blob/master/konf-core/src/main/kotlin/com/uchuhimo/konf/source/DefaultLoaders.kt), shown below (the corresponding config spec for these samples is [`ConfigForLoad`](https://github.com/uchuhimo/konf/blob/master/konf-core/src/test/kotlin/com/uchuhimo/konf/source/ConfigForLoad.kt)):\n\n| Type                                                         | Usage                            | Provider                                                     | Sample                                                       |\n| ------------------------------------------------------------ | -------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |\n| [HOCON](https://github.com/typesafehub/config/blob/master/HOCON.md) | `config.from.hocon`              | [`HoconProvider`](https://github.com/uchuhimo/konf/blob/master/konf-hocon/src/main/kotlin/com/uchuhimo/konf/source/hocon/HoconProvider.kt) | [`source.conf`](https://github.com/uchuhimo/konf/blob/master/konf-hocon/src/test/resources/source/source.conf) |\n| JSON                                                         | `config.from.json`               | [`JsonProvider`](https://github.com/uchuhimo/konf/blob/master/konf-core/src/main/kotlin/com/uchuhimo/konf/source/json/JsonProvider.kt) | [`source.json`](https://github.com/uchuhimo/konf/blob/master/konf-core/src/test/resources/source/source.json) |\n| properties                                                   | `config.from.properties`         | [`PropertiesProvider`](https://github.com/uchuhimo/konf/blob/master/konf-core/src/main/kotlin/com/uchuhimo/konf/source/properties/PropertiesProvider.kt) | [`source.properties`](https://github.com/uchuhimo/konf/blob/master/konf-core/src/test/resources/source/source.properties) |\n| [TOML](https://github.com/toml-lang/toml)                    | `config.from.toml`               | [`TomlProvider`](https://github.com/uchuhimo/konf/blob/master/konf-toml/src/main/kotlin/com/uchuhimo/konf/source/toml/TomlProvider.kt) | [`source.toml`](https://github.com/uchuhimo/konf/blob/master/konf-toml/src/test/resources/source/source.toml) |\n| XML                                                          | `config.from.xml`                | [`XmlProvider`](https://github.com/uchuhimo/konf/blob/master/konf-xml/src/main/kotlin/com/uchuhimo/konf/source/xml/XmlProvider.kt) | [`source.xml`](https://github.com/uchuhimo/konf/blob/master/konf-xml/src/test/resources/source/source.xml) |\n| YAML                                                         | `config.from.yaml`               | [`YamlProvider`](https://github.com/uchuhimo/konf/blob/master/konf-yaml/src/main/kotlin/com/uchuhimo/konf/source/yaml/YamlProvider.kt) | [`source.yaml`](https://github.com/uchuhimo/konf/blob/master/konf-yaml/src/test/resources/source/source.yaml) |\n| JavaScript                                                   | `config.from.js`                 | [`JsProvider`](https://github.com/uchuhimo/konf/blob/master/konf-js/src/main/kotlin/com/uchuhimo/konf/source/js/JsProvider.kt) | [`source.js`](https://github.com/uchuhimo/konf/blob/master/konf-js/src/test/resources/source/source.js) |\n| hierarchical map                                             | `config.from.map.hierarchical`   | -                                                            | [`MapSourceLoadSpec`](https://github.com/uchuhimo/konf/blob/master/konf-core/src/test/kotlin/com/uchuhimo/konf/source/base/MapSourceLoadSpec.kt) |\n| map in key-value format                                      | `config.from.map.kv`             | -                                                            | [`KVSourceSpec`](https://github.com/uchuhimo/konf/blob/master/konf-core/src/test/kotlin/com/uchuhimo/konf/source/base/KVSourceSpec.kt) |\n| map in flat format                                           | `config.from.map.flat`           | -                                                            | [`FlatSourceLoadSpec`](https://github.com/uchuhimo/konf/blob/master/konf-core/src/test/kotlin/com/uchuhimo/konf/source/base/FlatSourceLoadSpec.kt) |\n| system environment                                           | `config.from.env()`              | [`EnvProvider`](https://github.com/uchuhimo/konf/blob/master/konf-core/src/main/kotlin/com/uchuhimo/konf/source/env/EnvProvider.kt) | -                                                            |\n| system properties                                            | `config.from.systemProperties()` | [`PropertiesProvider`](https://github.com/uchuhimo/konf/blob/master/konf-core/src/main/kotlin/com/uchuhimo/konf/source/properties/PropertiesProvider.kt) | -                                                            |\n\nThese sources can also be manually created using their provider, and then loaded into config by `config.withSource(source)`.\n\nAll `from` APIs also have their standalone version that return sources without loading them into the config, shown below:\n\n| Type                                                         | Usage                            |\n| ------------------------------------------------------------ | -------------------------------- |\n| [HOCON](https://github.com/typesafehub/config/blob/master/HOCON.md) | `Source.from.hocon`              |\n| JSON                                                         | `Source.from.json`               |\n| properties                                                   | `Source.from.properties`         |\n| [TOML](https://github.com/toml-lang/toml)                    | `Source.from.toml`               |\n| XML                                                          | `Source.from.xml`                |\n| YAML                                                         | `Source.from.yaml`               |\n| JavaScript                                                   | `Source.from.js`                 |\n| hierarchical map                                             | `Source.from.map.hierarchical`   |\n| map in key-value format                                      | `Source.from.map.kv`             |\n| map in flat format                                           | `Source.from.map.flat`           |\n| system environment                                           | `Source.from.env()`              |\n| system properties                                            | `Source.from.systemProperties()` |\n\nFormat of system properties source is same with that of properties source. System environment source follows the same mapping convention with properties source, but with the following name convention:\n\n- All letters in name are in uppercase\n- `.` in name is replaced with `_`\n\nHOCON/JSON/properties/TOML/XML/YAML/JavaScript source can be loaded from a variety of input format. Use properties source as example:\n\n- From file: `config.from.properties.file(\"/path/to/file\")`\n- From watched file: `config.from.properties.watchFile(\"/path/to/file\", 100, TimeUnit.MILLISECONDS)`\n  - You can re-trigger the setup process every time the updated file is loaded by `watchFile(\"/path/to/file\") { config, source -\u003e setup(config) }`\n- From string: `config.from.properties.string(\"server.port = 8080\")`\n- From URL: `config.from.properties.url(\"http://localhost:8080/source.properties\")`\n- From watched URL: `config.from.properties.watchUrl(\"http://localhost:8080/source.properties\", 1, TimeUnit.MINUTES)`\n  - You can re-trigger the setup process every time the URL is loaded by `watchUrl(\"http://localhost:8080/source.properties\") { config, source -\u003e setup(config) }`\n- From Git repository: `config.from.properties.git(\"https://github.com/uchuhimo/konf.git\", \"/path/to/source.properties\", branch = \"dev\")`\n- From watched Git repository: `config.from.properties.watchGit(\"https://github.com/uchuhimo/konf.git\", \"/path/to/source.properties\", period = 1, unit = TimeUnit.MINUTES)`\n  - You can re-trigger the setup process every time the Git file is loaded by `watchGit(\"https://github.com/uchuhimo/konf.git\", \"/path/to/source.properties\") { config, source -\u003e setup(config) }`\n- From resource: `config.from.properties.resource(\"source.properties\")`\n- From reader: `config.from.properties.reader(reader)`\n- From input stream: `config.from.properties.inputStream(inputStream)`\n- From byte array: `config.from.properties.bytes(bytes)`\n- From portion of byte array: `config.from.properties.bytes(bytes, 1, 12)`\n\nIf source is from file, file extension can be auto detected. Thus, you can use `config.from.file(\"/path/to/source.json\")` instead of `config.from.json.file(\"/path/to/source.json\")`, or use `config.from.watchFile(\"/path/to/source.json\")` instead of `config.from.json.watchFile(\"/path/to/source.json\")`. Source from URL also support auto-detected extension (use `config.from.url` or `config.from.watchUrl`). The following file extensions can be supported:\n\n| Type       | Extension  |\n| ---------- | ---------- |\n| HOCON      | conf       |\n| JSON       | json       |\n| Properties | properties |\n| TOML       | toml       |\n| XML        | xml        |\n| YAML       | yml, yaml  |\n| JavaScript | js         |\n\nYou can also implement [`Source`](https://github.com/uchuhimo/konf/blob/master/konf-core/src/main/kotlin/com/uchuhimo/konf/source/Source.kt) to customize your new source, which can be loaded into config by `config.withSource(source)`.\n\n### Subscribe the update event for load operation\n\nSubscribe the update event before every load operation:\n\n```kotlin\nval handler = config.beforeLoad { source -\u003e println(\"$source will be loaded\") }\n```\n\nYou can re-trigger the setup process by subscribing the update event after every load operation:\n\n```kotlin\nval handler = config.afterLoad { source -\u003e setup(config) }\n```\n\nCancel the subscription:\n\n```kotlin\nhandler.cancel()\n```\n\n### Strict parsing when loading\n\nBy default, Konf extracts desired paths from sources and ignores other unknown paths in sources. If you want Konf to throws exception when unknown paths are found, you can enable `FAIL_ON_UNKNOWN_PATH` feature:\n\n```kotlin\nconfig.enable(Feature.FAIL_ON_UNKNOWN_PATH)\n    .from.properties.file(\"server.properties\")\n    .from.json.resource(\"server.json\")\n```\n\nThen `config` will validate paths from both the properties file and the JSON resource. Furthermore, If you want to validate the properties file only, you can use:\n\n```kotlin\nconfig.from.enable(Feature.FAIL_ON_UNKNOWN_PATH).properties.file(\"/path/to/file\")\n    .from.json.resource(\"server.json\")\n```\n\n### Path substitution\n\nPath substitution is a feature that path references in source will be substituted by their values.\n\nPath substitution rules are shown below:\n\n- Only quoted string value will be substituted. It means that Konf's path substitutions will not conflict with HOCON's substitutions.\n- The definition of a path variable is `${path}`, e.g., `${java.version}`.\n- The path variable is resolved in the context of the current source.\n- If the string value only contains the path variable, it will be replaced by the whole sub-tree in the path; otherwise, it will be replaced by the string value in the path.\n- Use `${path:-default}` to provide a default value when the path is unresolved, e.g., `${java.version:-8}`.\n- Use `$${path}` to escape the path variable, e.g., `$${java.version}` will be resolved to `${java.version}` instead of the value in `java.version`.\n- Path substitution works in a recursive way, so nested path variables like `${jre-${java.specification.version}}` are allowed.\n- Konf also supports all key prefix of [StringSubstitutor](https://commons.apache.org/proper/commons-text/apidocs/org/apache/commons/text/StringSubstitutor.html)'s default interpolator. \n\nBy default, Konf will perform path substitution for every source (except system environment source) when loading them into the config.\nYou can disable this behaviour by using `config.disable(Feature.SUBSTITUTE_SOURCE_BEFORE_LOADED)` for the config \nor `source.disabled(Feature.SUBSTITUTE_SOURCE_BEFORE_LOADED)` for a single source.\n\nBy default, Konf will throw exception when some path variables are unresolved. You can use `source.substituted(false)` manually to ignore these unresolved variables.\n\nTo resolve path variables refer to other sources, you can merge these sources before loading them into the config.\nFor example, if we have two sources `source1.json` and `source2.properties`,\n`source1.json` is:\n\n```json\n{ \n  \"base\" : { \"user\" : \"konf\" , \"password\" : \"passwd\" }\n}\n```\n\n`source2.properties` is:\n\n```properties\nconnection.jdbc=mysql://${base.user}:${base.password}@server:port\n```\n\nuse:\n\n```kotlin\nconfig.withSource(\n    Source.from.file(\"source1.json\") +\n    Source.from.file(\"source2.properties\")\n)\n```\n\nWe can resolve `mysql://${base.user}:${base.password}@server:port` as `mysql://konf:passwd@server:port`.\n\n## Prefix/Merge operations for source/config/config spec\n\nAll of source/config/config spec support add prefix operation, remove prefix operation and merge operation as shown below:\n\n| Type     | Add Prefix                                                   | Remove Prefix                                               | Merge                                                  |\n| -------- | ------------------------------------------------------------ | ----------------------------------------------------------- | ------------------------------------------------------ |\n| `Source` | `source.withPrefix(prefix)` or `Prefix(prefix) + source` or `config.from.prefixed(prefix).file(file)` | `source[prefix]` or `config.from.scoped(prefix).file(file)` | `fallback + facade` or `facade.withFallback(fallback)` |\n| `Config` | `config.withPrefix(prefix)` or `Prefix(prefix) + config`     | `config.at(prefix)`                                         | `fallback + facade` or `facade.withFallback(fallback)` |\n| `Spec`   | `spec.withPrefix(prefix)` or `Prefix(prefix) + spec`         | `spec[prefix]`                                              | `fallback + facade` or `facade.withFallback(fallback)` |\n\n## Export/Reload values in config\n\nExport all values in config as a tree:\n\n```kotlin\nval tree = config.toTree()\n```\n\nExport all values in config to map in key-value format:\n\n```kotlin\nval map = config.toMap()\n```\n\nExport all values in config to hierarchical map:\n\n```kotlin\nval map = config.toHierarchicalMap()\n```\n\nExport all values in config to map in flat format:\n\n```kotlin\nval map = config.toFlatMap()\n```\n\nExport all values in config to JSON:\n\n```kotlin\nval file = createTempFile(suffix = \".json\")\nconfig.toJson.toFile(file)\n```\n\nReload values from JSON:\n\n```kotlin\nval newConfig = Config {\n    addSpec(Server)\n}.from.json.file(file)\ncheck(config == newConfig)\n```\n\nConfig can be saved to a variety of output format in HOCON/JSON/properties/TOML/XML/YAML/JavaScript. Use JSON as example:\n\n- To file: `config.toJson.toFile(\"/path/to/file\")`\n- To string: `config.toJson.toText()`\n- To writer: `config.toJson.toWriter(writer)`\n- To output stream: `config.toJson.toOutputStream(outputStream)`\n- To byte array: `config.toJson.toBytes()`\n\nYou can also implement [`Writer`](https://github.com/uchuhimo/konf/blob/master/konf-core/src/main/kotlin/com/uchuhimo/konf/source/Writer.kt) to customize your new writer (see [`JsonWriter`](https://github.com/uchuhimo/konf/blob/master/konf-core/src/main/kotlin/com/uchuhimo/konf/source/json/JsonWriter.kt) for how to integrate your writer with config).\n\n## Supported item types\n\nSupported item types include:\n\n- All primitive types\n- All primitive array types\n- `BigInteger`\n- `BigDecimal`\n- `String`\n- Date and Time\n    - `java.util.Date`\n    - `OffsetTime`\n    - `OffsetDateTime`\n    - `ZonedDateTime`\n    - `LocalDate`\n    - `LocalTime`\n    - `LocalDateTime`\n    - `Year`\n    - `YearMonth`\n    - `Instant`\n    - `Duration`\n- `SizeInBytes`\n- Enum\n- Array\n- Collection\n    - `List`\n    - `Set`\n    - `SortedSet`\n    - `Map`\n    - `SortedMap`\n- Kotlin Built-in classes\n    - `Pair`\n    - `Triple`\n    - `IntRange`\n    - `CharRange`\n    - `LongRange`\n- Data classes\n- POJOs supported by Jackson core modules\n\nKonf supports size in bytes format described in [HOCON document](https://github.com/typesafehub/config/blob/master/HOCON.md#size-in-bytes-format) with class `SizeInBytes`.\n\nKonf supports both [ISO-8601 duration format](https://en.wikipedia.org/wiki/ISO_8601#Durations) and [HOCON duration format](https://github.com/typesafehub/config/blob/master/HOCON.md#duration-format) for `Duration`.\n\nKonf uses [Jackson](https://github.com/FasterXML/jackson) to support Kotlin Built-in classes, Data classes and POJOs. You can use `config.mapper` to access `ObjectMapper` instance used by config, and configure it to support more types from third-party Jackson modules. Default modules registered by Konf include:\n\n- Jackson core modules\n- `JavaTimeModule` in [jackson-modules-java8](https://github.com/FasterXML/jackson-modules-java8)\n- [jackson-module-kotlin](https://github.com/FasterXML/jackson-module-kotlin)\n\n## Optional features\n\nThere are some optional features that you can enable/disable in the config scope or the source scope by `Config#enable(Feature)`/`Config#disable(Feature)` or `Source#enabled(Feature)`/`Source#disable(Feature)`. You can use `Config#isEnabled()` or `Source#isEnabled()` to check whether a feature is enabled.\n\nThese features include:\n\n- `FAIL_ON_UNKNOWN_PATH`: feature that determines what happens when unknown paths appear in the source. If enabled, an exception is thrown when loading from the source to indicate it contains unknown paths. This feature is disabled by default.\n- `LOAD_KEYS_CASE_INSENSITIVELY`: feature that determines whether loading keys from sources case-insensitively. This feature is disabled by default except for system environment.\n- `LOAD_KEYS_AS_LITTLE_CAMEL_CASE`: feature that determines whether loading keys from sources as little camel case. This feature is enabled by default.\n- `OPTIONAL_SOURCE_BY_DEFAULT`: feature that determines whether sources are optional by default. This feature is disabled by default.\n- `SUBSTITUTE_SOURCE_BEFORE_LOADED`: feature that determines whether sources should be substituted before loaded into config. This feature is enabled by default.\n\n## Build from source\n\nBuild library with Gradle using the following command:\n\n```\n./gradlew clean assemble\n```\n\nTest library with Gradle using the following command:\n\n```\n./gradlew clean test\n```\n\nSince Gradle has excellent incremental build support, you can usually omit executing the `clean` task.\n\nInstall library in a local Maven repository for consumption in other projects via the following command:\n\n```\n./gradlew clean install\n```\n\n## Breaking Changes\n\n### v0.19.0\n\nSince all sources are substituted before loaded into config by default, all path variables will be substituted now. You can use `config.disable(Feature.SUBSTITUTE_SOURCE_BEFORE_LOADED)` to disable this change.\n\n### v0.17.0\n\nAfter migrated to tree-based source APIs, many deprecated APIs are removed, including:\n\n- `Source`: all `isXXX` and `toXXX` APIs\n- `Config`: `layer`, `addSource` and `withSourceFrom`\n\n### v0.15\n\nAfter modularized Konf, `hocon`/`toml`/`xml`/`yaml`/`git`/`watchGit` in `DefaultLoaders` become extension properties/functions and should be imported explicitly.\nFor example, you should import `com.uchuhimo.konf.source.hocon` before using `config.from.hocon`; in Java, `config.from().hocon` is unavailable, please use `config.from().source(HoconProvider.INSTANCE)` instead.\n\nIf you use JitPack, you should use `com.github.uchuhimo.konf:konf:\u003cversion\u003e` instead of `com.github.uchuhimo:konf:\u003cversion\u003e` now.\n\n### v0.10\n\nAPIs in `ConfigSpec` have been updated to support item name's auto-detection, please migrate to new APIs. Here are some examples:\n\n- `val host = optional(\"host\", \"0.0.0.0\")` to `val host by optional(\"0.0.0.0\")`\n- `val port = required\u003cInt\u003e(\"port\")` to `val port by required\u003cInt\u003e()`\n- `val nextPort = lazy(\"nextPort\") { config -\u003e config[port] + 1 }` to `val nextPort by lazy { config -\u003e config[port] + 1 }`\n\n# License\n\n© uchuhimo, 2017-2019. Licensed under an [Apache 2.0](./LICENSE) license.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuchuhimo%2Fkonf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fuchuhimo%2Fkonf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuchuhimo%2Fkonf/lists"}