{"id":20905183,"url":"https://github.com/akkadotnet/hocon","last_synced_at":"2025-04-04T09:09:50.890Z","repository":{"id":35986854,"uuid":"40278472","full_name":"akkadotnet/HOCON","owner":"akkadotnet","description":"C# implementation of Lightbend's HOCON (Human-Optimized Object Configuration Notation)","archived":false,"fork":false,"pushed_at":"2023-02-21T14:59:27.000Z","size":1231,"stargazers_count":139,"open_issues_count":38,"forks_count":39,"subscribers_count":12,"default_branch":"dev","last_synced_at":"2025-03-28T08:09:29.224Z","etag":null,"topics":["hocon","hocon-configuration"],"latest_commit_sha":null,"homepage":"","language":"C#","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/akkadotnet.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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-08-06T01:54:34.000Z","updated_at":"2025-03-11T13:00:42.000Z","dependencies_parsed_at":"2024-06-18T15:20:56.949Z","dependency_job_id":"d3a8b643-89d6-433d-9458-b801ea1cc3a1","html_url":"https://github.com/akkadotnet/HOCON","commit_stats":{"total_commits":190,"total_committers":18,"mean_commits":"10.555555555555555","dds":0.7052631578947368,"last_synced_commit":"90dd630040a9b2f1cdedc6bc95e465aa23ac500b"},"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akkadotnet%2FHOCON","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akkadotnet%2FHOCON/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akkadotnet%2FHOCON/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akkadotnet%2FHOCON/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/akkadotnet","download_url":"https://codeload.github.com/akkadotnet/HOCON/tar.gz/refs/heads/dev","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247149502,"owners_count":20891954,"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":["hocon","hocon-configuration"],"created_at":"2024-11-18T13:22:57.341Z","updated_at":"2025-04-04T09:09:50.870Z","avatar_url":"https://github.com/akkadotnet.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# HOCON (Human-Optimized Config Object Notation)\n\nC# implementation of Typesafe's HOCON (Human-Optimized Object Configuration Notation)\n\n## Installation\nTo install [HOCON via NuGet](https://www.nuget.org/packages/Hocon.Configuration/):\n\n```\nPS\u003e Install-Package Hocon.Configuration\n```\n\n### Nightly Build Access\nIf you need access to nightly HOCON builds, you can [get them via the Akka.NET nightly build NuGet feed](https://getakka.net/community/getting-access-to-nightly-builds.html).\n\n# Spec\n\nThis is an informal spec, but hopefully it's clear.\n\n## Goals / Background\n\nThe primary goal is: keep the semantics (tree structure; set of\ntypes; encoding/escaping) from JSON (JavaScript Object Notation),\nbut make it more convenient as a human-editable config file format.\n\nThe following features are desirable, to support human usage:\n\n - less noisy / less pedantic syntax\n - ability to refer to another part of the configuration (set a value to\n   another value)\n - import/include another configuration file into the current file\n - a mapping to a flat properties list such as Java's system properties\n - ability to get values from environment variables\n - ability to write comments\n\nImplementation-wise, the format should have these properties:\n\n - a JSON superset, that is, all valid JSON should be valid and\n   should result in the same in-memory data that a JSON parser\n   would have produced.\n - be deterministic; the format is flexible, but it is not\n   heuristic. It should be clear what's invalid and invalid files\n   should generate errors.\n - require minimal look-ahead; should be able to tokenize the file\n   by looking at only the next three characters. (right now, the\n   only reason to look at three is to find \"//\" comments;\n   otherwise you can parse looking at two.)\n\nHOCON is significantly harder to specify and to parse than\nJSON. Think of it as moving the work from the person maintaining\nthe config file to the computer program.\n\n## Default HOCON Configuration Sources\nBy default the HOCON library will look for HOCON configurations in the following locations whenever you call the `Hocon.Configuration.ConfigurationFactory.Default()` method:\n\n1. [.NET Core / .NET Framework] An \"app.conf\" or an \"app.hocon\" file in the current working directory of the executable when it loads;\n2. [.NET Framework] - the `\u003chocon\u003e` `ConfigurationSection` inside `App.config` or `Web.config`; or\n3. [.NET Framework] - and a legacy option, to load the old `\u003cakka\u003e` HOCON section for backwards compatibility purposes with all users who have been using HOCON with Akka.NET.\n\n## Definitions\n\n - a _key_ is a string JSON would have to the left of `:` and a _value_ is\n   anything JSON would have to the right of `:`. i.e. the two\n   halves of an object _field_.\n\n - a _value_ is any \"value\" as defined in the JSON spec, plus\n   unquoted strings and substitutions as defined in this spec.\n\n - a _simple value_ is any value excluding an object or array\n   value.\n\n - a _field_ is a key, any separator such as ':', and a value.\n\n - references to a _file_ (\"the file being parsed\") can be\n   understood to mean any byte stream being parsed, not just\n   literal files in a filesystem.\n\n## Syntax\n\nMuch of this is defined with reference to JSON; you can find the\nJSON spec at http://json.org/ of course.\n\n### Unchanged from JSON\n\n - files must be valid UTF-8\n - quoted strings are in the same format as JSON strings\n - values have possible types: string, number, object, array, boolean, null\n - allowed number formats matches JSON; as in JSON, some possible\n   floating-point values are not represented, such as `NaN`\n\n### Comments\n\nAnything between `//` or `#` and the next newline is considered a comment\nand ignored, unless the `//` or `#` is inside a quoted string.\n\n### Omit root braces\n\nJSON documents must have an array or object at the root. Empty\nfiles are invalid documents, as are files containing only a\nnon-array non-object value such as a string.\n\nIn HOCON, if the file does not begin with a square bracket or\ncurly brace, it is parsed as if it were enclosed with `{}` curly\nbraces.\n\nA HOCON file is invalid if it omits the opening `{` but still has\na closing `}`; the curly braces must be balanced.\n\n### Key-value separator\n\nThe `=` character can be used anywhere JSON allows `:`, i.e. to\nseparate keys from values.\n\nIf a key is followed by `{`, the `:` or `=` may be omitted. So\n`\"foo\" {}` means `\"foo\" : {}`\n\n### Commas\n\nValues in arrays, and fields in objects, need not have a comma\nbetween them as long as they have at least one ASCII newline\n(`\\n`, decimal value 10) between them.\n\nThe last element in an array or last field in an object may be\nfollowed by a single comma. This extra comma is ignored.\n\n - `[1,2,3,]` and `[1,2,3]` are the same array.\n - `[1\\n2\\n3]` and `[1,2,3]` are the same array.\n - `[1,2,3,,]` is invalid because it has two trailing commas.\n - `[,1,2,3]` is invalid because it has an initial comma.\n - `[1,,2,3]` is invalid because it has two commas in a row.\n - these same comma rules apply to fields in objects.\n\n### Whitespace\n\nThe JSON spec simply says \"whitespace\"; in HOCON whitespace is\ndefined as follows:\n\n - any Unicode space separator (Zs category), line separator (Zl\n   category), or paragraph separator (Zp category), including\n   nonbreaking spaces (such as 0x00A0, 0x2007, and 0x202F).\n   The BOM (0xFEFF) must also be treated as whitespace.\n - tab (`\\t` 0x0009), newline ('\\n' 0x000A), vertical tab ('\\v'\n   0x000B)`, form feed (`\\f' 0x000C), carriage return ('\\r'\n   0x000D), file separator (0x001C), group separator (0x001D),\n   record separator (0x001E), unit separator (0x001F).\n\nIn Java, the `isWhitespace()` method covers these characters with\nthe exception of nonbreaking spaces and the BOM.\n\nWhile all Unicode separators should be treated as whitespace, in\nthis spec \"newline\" refers only and specifically to ASCII newline\n0x000A.\n\n### Duplicate keys and object merging\n\nThe JSON spec does not clarify how duplicate keys in the same\nobject should be handled. In HOCON, duplicate keys that appear\nlater override those that appear earlier, unless both values are\nobjects. If both values are objects, then the objects are merged.\n\nNote: this would make HOCON a non-superset of JSON if you assume\nthat JSON requires duplicate keys to have a behavior. The\nassumption here is that duplicate keys are invalid JSON.\n\nTo merge objects:\n\n - add fields present in only one of the two objects to the merged\n   object.\n - for non-object-valued fields present in both objects,\n   the field found in the second object must be used.\n - for object-valued fields present in both objects, the\n   object values should be recursively merged according to\n   these same rules.\n\nObject merge can be prevented by setting the key to another value\nfirst. This is because merging is always done two values at a\ntime; if you set a key to an object, a non-object, then an object,\nfirst the non-object falls back to the object (non-object always\nwins), and then the object falls back to the non-object (no\nmerging, object is the new value). So the two objects never see\neach other.\n\nThese two are equivalent:\n\n```hocon\n{\n    \"foo\" : { \"a\" : 42 },\n    \"foo\" : { \"b\" : 43 }\n}\n\n{\n    \"foo\" : { \"a\" : 42, \"b\" : 43 }\n}\n```\n\nAnd these two are equivalent:\n\n```hocon\n{\n    \"foo\" : { \"a\" : 42 },\n    \"foo\" : null,\n    \"foo\" : { \"b\" : 43 }\n}\n\n{\n    \"foo\" : { \"b\" : 43 }\n}\n```\n\nThe intermediate setting of `\"foo\"` to `null` prevents the object merge.\n\n### Unquoted strings\n\nA sequence of characters outside of a quoted string is a string\nvalue if:\n\n - it does not contain \"forbidden characters\": \"$\", '\"', '{', '}',\n   '[', ']', ':', '=', ',', '+', '#', '`', '^', '?', '!', '@',\n   '*', '\u0026', '\\' (backslash), or whitespace.\n - it does not contain the two-character string \"//\" (which\n   starts a comment)\n - its initial characters do not parse as `true`, `false`, `null`,\n   or a number.\n\nUnquoted strings are used literally, they do not support any kind\nof escaping. Quoted strings may always be used as an alternative\nwhen you need to write a character that is not permitted in an\nunquoted string.\n\n`truefoo` parses as the boolean token `true` followed by the\nunquoted string `foo`. However, `footrue` parses as the unquoted\nstring `footrue`. Similarly, `10.0bar` is the number `10.0` then\nthe unquoted string `bar` but `bar10.0` is the unquoted string\n`bar10.0`. (In practice, this distinction doesn't matter much\nbecause of value concatenation; see later section.)\n\nIn general, once an unquoted string begins, it continues until a\nforbidden character or the two-character string \"//\" is\nencountered. Embedded (non-initial) booleans, nulls, and numbers\nare not recognized as such, they are part of the string.\n\nAn unquoted string may not _begin_ with the digits 0-9 or with a\nhyphen (`-`, 0x002D) because those are valid characters to begin a\nJSON number. The initial number character, plus any valid-in-JSON\nnumber characters that follow it, must be parsed as a number\nvalue. Again, these characters are not special _inside_ an\nunquoted string; they only trigger number parsing if they appear\ninitially.\n\nNote that quoted JSON strings may not contain control characters\n(control characters include some whitespace characters, such as\nnewline). This rule is from the JSON spec. However, unquoted\nstrings have no restriction on control characters, other than the\nones listed as \"forbidden characters\" above.\n\nSome of the \"forbidden characters\" are forbidden because they\nalready have meaning in JSON or HOCON, others are essentially\nreserved keywords to allow future extensions to this spec.\n\n### Multi-line strings\n\nMulti-line strings are similar to Python or Scala, using triple\nquotes. If the three-character sequence `\"\"\"` appears, then all\nUnicode characters until a closing `\"\"\"` sequence are used\nunmodified to create a string value. Newlines and whitespace\nreceive no special treatment. Unlike Scala, and unlike JSON quoted\nstrings, Unicode escapes are not interpreted in triple-quoted\nstrings.\n\nIn Python, `\"\"\"foo\"\"\"\"` is a syntax error (a triple-quoted string\nfollowed by a dangling unbalanced quote). In Scala, it is a\nfour-character string `foo\"`. HOCON works like Scala; any sequence\nof at least three quotes ends the multi-line string, and any\n\"extra\" quotes are part of the string.\n\n### Value concatenation\n\nThe value of an object field or array element may consist of\nmultiple values which are combined. There are three kinds of value\nconcatenation:\n\n - if all the values are simple values (neither objects nor\n   arrays), they are concatenated into a string.\n - if all the values are arrays, they are concatenated into\n   one array.\n - if all the values are objects, they are merged (as with\n   duplicate keys) into one object.\n\nString value concatenation is allowed in field keys, in addition\nto field values and array elements. Objects and arrays do not make\nsense as field keys.\n\nNote: Akka 2.0 (and thus Play 2.0) contains an embedded\nimplementation of the config lib which does not support array and\nobject value concatenation; it only supports string value\nconcatenation.\n\n#### String value concatenation\n\nString value concatenation is the trick that makes unquoted\nstrings work; it also supports substitutions (`${foo}` syntax) in\nstrings.\n\nOnly simple values participate in string value\nconcatenation. Recall that a simple value is any value other than\narrays and objects.\n\nAs long as simple values are separated only by non-newline\nwhitespace, the _whitespace between them is preserved_ and the\nvalues, along with the whitespace, are concatenated into a string.\n\nString value concatenations never span a newline, or a character\nthat is not part of a simple value.\n\nA string value concatenation may appear in any place that a string\nmay appear, including object keys, object values, and array\nelements.\n\nWhenever a value would appear in JSON, a HOCON parser instead\ncollects multiple values (including the whitespace between them)\nand concatenates those values into a string.\n\nWhitespace before the first and after the last simple value must\nbe discarded. Only whitespace _between_ simple values must be\npreserved.\n\nSo for example ` foo bar baz ` parses as three unquoted strings,\nand the three are value-concatenated into one string. The inner\nwhitespace is kept and the leading and trailing whitespace is\ntrimmed. The equivalent string, written in quoted form, would be\n`\"foo bar baz\"`.\n\nValue concatenating `foo bar` (two unquoted strings with\nwhitespace) and quoted string `\"foo bar\"` would result in the same\nin-memory representation, seven characters.\n\nFor purposes of string value concatenation, non-string values are\nconverted to strings as follows (strings shown as quoted strings):\n\n - `true` and `false` become the strings `\"true\"` and `\"false\"`.\n - `null` becomes the string `\"null\"`.\n - quoted and unquoted strings are themselves.\n - numbers should be kept as they were originally written in the\n   file. For example, if you parse `1e5` then you might render\n   it alternatively as `1E5` with capital `E`, or just `100000`.\n   For purposes of value concatenation, it should be rendered\n   as it was written in the file.\n - a substitution is replaced with its value which is then\n   converted to a string as above.\n - it is invalid for arrays or objects to appear in a string value\n   concatenation.\n\nA single value is never converted to a string. That is, it would\nbe wrong to value concatenate `true` by itself; that should be\nparsed as a boolean-typed value. Only `true foo` (`true` with\nanother simple value on the same line) should be parsed as a value\nconcatenation and converted to a string.\n\n#### Array and object concatenation\n\nArrays can be concatenated with arrays, and objects with objects,\nbut it is an error if they are mixed.\n\nFor purposes of concatenation, \"array\" also means \"substitution\nthat resolves to an array\" and \"object\" also means \"substitution\nthat resolves to an object.\"\n\nWithin an field value or array element, if only non-newline\nwhitespace separates the end of a first array or object or\nsubstitution from the start of a second array or object or\nsubstitution, the two values are concatenated. Newlines may occur\n_within_ the array or object, but not _between_ them. Newlines\n_between_ prevent concatenation.\n\nFor objects, \"concatenation\" means \"merging\", so the second object\noverrides the first.\n\nArrays and objects cannot be field keys, whether concatenation is\ninvolved or not.\n\nHere are several ways to define `a` to the same object value:\n\n```hocon\n// one object\na : { b : 1, c : 2 }\n// two objects that are merged via concatenation rules\na : { b : 1 } { c : 2 }\n// two fields that are merged\na : { b : 1 }\na : { c : 2 }\n```\n\nHere are several ways to define `a` to the same array value:\n\n```hocon\n// one array\na : [ 1, 2, 3, 4 ]\n// two arrays that are concatenated\na : [ 1, 2 ] [ 3, 4 ]\n// a later definition referring to an earlier\n// (see \"self-referential substitutions\" below)\na : [ 1, 2 ]\na : ${a} [ 3, 4 ]\n```\n\nA common use of object concatenation is \"inheritance\":\n\n```hocon\ndata-center-generic = { cluster-size = 6 }\ndata-center-east = ${data-center-generic} { name = \"east\" }\n```\n\nA common use of array concatenation is to add to paths:\n\n```hocon\npath = [ /bin ]\npath = ${path} [ /usr/bin ]\n```\n\n#### Note: Arrays without commas or newlines\n\nArrays allow you to use newlines instead of commas, but not\nwhitespace instead of commas. Non-newline whitespace will produce\nconcatenation rather than separate elements.\n\n```hocon\n// this is an array with one element, the string \"1 2 3 4\"\n[ 1 2 3 4 ]\n// this is an array of four integers\n[ 1\n  2\n  3\n  4 ]\n\n// an array of one element, the array [ 1, 2, 3, 4 ]\n[ [ 1, 2 ] [ 3, 4 ] ]\n// an array of two arrays\n[ [ 1, 2 ]\n  [ 3, 4 ] ]\n```\n\nIf this gets confusing, just use commas. The concatenation\nbehavior is useful rather than surprising in cases like:\n\n```hocon\n[ This is an unquoted string my name is ${name}, Hello ${world} ]\n[ ${a} ${b}, ${x} ${y} ]\n```\n\nNon-newline whitespace is never an element or field separator.\n\n### Path expressions\n\nPath expressions are used to write out a path through the object\ngraph. They appear in two places; in substitutions, like\n`${foo.bar}`, and as the keys in objects like `{ foo.bar : 42 }`.\n\nPath expressions are syntactically identical to a value\nconcatenation, except that they may not contain\nsubstitutions. This means that you can't nest substitutions inside\nother substitutions, and you can't have substitutions in keys.\n\nWhen concatenating the path expression, any `.` characters outside\nquoted strings are understood as path separators, while inside\nquoted strings `.` has no special meaning. So\n`foo.bar.\"hello.world\"` would be a path with three elements,\nlooking up key `foo`, key `bar`, then key `hello.world`.\n\nThe main tricky point is that `.` characters in numbers do count\nas a path separator. When dealing with a number as part of a path\nexpression, it's essential to retain the _original_ string\nrepresentation of the number as it appeared in the file (rather\nthan converting it back to a string with a generic\nnumber-to-string library function).\n\n - `10.0foo` is a number then unquoted string `foo` and should\n   be the two-element path with `10` and `0foo` as the elements.\n - `foo10.0` is an unquoted string with a `.` in it, so this would\n   be a two-element path with `foo10` and `0` as the elements.\n - `foo\"10.0\"` is an unquoted then a quoted string which are\n   concatenated, so this is a single-element path.\n - `1.2.3` is the three-element path with `1`,`2`,`3`\n\nUnlike value concatenations, path expressions are _always_\nconverted to a string, even if they are just a single value.\n\nIf you have an array or element value consisting of the single\nvalue `true`, it's a value concatenation and retains its character\nas a boolean value.\n\nIf you have a path expression (in a key or substitution) then it\nmust always be converted to a string, so `true` becomes the string\nthat would be quoted as `\"true\"`.\n\nIf a path element is an empty string, it must always be quoted.\nThat is, `a.\"\".b` is a valid path with three elements, and the\nmiddle element is an empty string. But `a..b` is invalid and\nshould generate an error. Following the same rule, a path that\nstarts or ends with a `.` is invalid and should generate an error.\n\n### Paths as keys\n\nIf a key is a path expression with multiple elements, it is\nexpanded to create an object for each path element other than the\nlast. The last path element, combined with the value, becomes a\nfield in the most-nested object.\n\nIn other words:\n\n```hocon\nfoo.bar : 42\n```\n\nis equivalent to:\n\n```hocon\nfoo { bar : 42 }\n```\n\nand:\n\n```hocon\nfoo.bar.baz : 42\n```\n\nis equivalent to:\n\n```hocon\nfoo { bar { baz : 42 } }\n```\n\nand so on. These values are merged in the usual way; which implies\nthat:\n\n```hocon\na.x : 42, a.y : 43\n```\n\nis equivalent to:\n\n```hocon\na { x : 42, y : 43 }\n```\n\nBecause path expressions work like value concatenations, you can\nhave whitespace in keys:\n\n```hocon\na b c : 42\n```\n\nis equivalent to:\n\n```hocon\n\"a b c\" : 42\n```\n\nBecause path expressions are always converted to strings, even\nsingle values that would normally have another type become\nstrings.\n\n   - `true : 42` is `\"true\" : 42`\n   - `3 : 42` is `\"3\" : 42`\n   - `3.14 : 42` is `\"3\" : { \"14\" : 42 }`\n\nAs a special rule, the unquoted string `include` may not begin a\npath expression in a key, because it has a special interpretation\n(see below).\n\n### Substitutions\n\nSubstitutions are a way of referring to other parts of the\nconfiguration tree.\n\nThe syntax is `${pathexpression}` or `${?pathexpression}` where\nthe `pathexpression` is a path expression as described above. This\npath expression has the same syntax that you could use for an\nobject key.\n\nThe `?` in `${?pathexpression}` must not have whitespace before\nit; the three characters `${?` must be exactly like that, grouped\ntogether.\n\nFor substitutions which are not found in the configuration tree,\nimplementations may try to resolve them by looking at system\nenvironment variables or other external sources of configuration.\n(More detail on environment variables in a later section.)\n\nSubstitutions are not parsed inside quoted strings. To get a\nstring containing a substitution, you must use value concatenation\nwith the substitution in the unquoted portion:\n\n```hocon\nkey : ${animal.favorite} is my favorite animal\n```\n\nOr you could quote the non-substitution portion:\n\n```hocon\nkey : ${animal.favorite}\" is my favorite animal\"\n```\n\nSubstitutions are resolved by looking up the path in the\nconfiguration. The path begins with the root configuration object,\ni.e. it is \"absolute\" rather than \"relative.\"\n\nSubstitution processing is performed as the last parsing step, so\na substitution can look forward in the configuration. If a\nconfiguration consists of multiple files, it may even end up\nretrieving a value from another file.\n\nIf a key has been specified more than once, the substitution will\nalways evaluate to its latest-assigned value (that is, it will\nevaluate to the merged object, or the last non-object value that\nwas set, in the entire document being parsed including all\nincluded files).\n\nIf a configuration sets a value to `null` then it should not be\nlooked up in the external source. Unfortunately there is no way to\n\"undo\" this in a later configuration file; if you have `{ \"HOME\" :\nnull }` in a root object, then `${HOME}` will never look at the\nenvironment variable. There is no equivalent to JavaScript's\n`delete` operation in other words.\n\nIf a substitution does not match any value present in the\nconfiguration and is not resolved by an external source, then it\nis undefined. An undefined substitution with the `${foo}` syntax\nis invalid and should generate an error.\n\nIf a substitution with the `${?foo}` syntax is undefined:\n\n - if it is the value of an object field then the field should not\n   be created. If the field would have overridden a previously-set\n   value for the same field, then the previous value remains.\n - if it is an array element then the element should not be added.\n - if it is part of a value concatenation with another string then\n   it should become an empty string; if part of a value\n   concatenation with an object or array it should become an empty\n   object or array.\n - `foo : ${?bar}` would avoid creating field `foo` if `bar` is\n   undefined. `foo : ${?bar}${?baz}` would also avoid creating the\n   field if _both_ `bar` and `baz` are undefined.\n\nSubstitutions are only allowed in field values and array\nelements (value concatenations), they are not allowed in keys or\nnested inside other substitutions (path expressions).\n\nA substitution is replaced with any value type (number, object,\nstring, array, true, false, null). If the substitution is the only\npart of a value, then the type is preserved. Otherwise, it is\nvalue-concatenated to form a string.\n\n#### Self-Referential Substitutions\n\nThe big picture:\n\n - substitutions normally \"look forward\" and use the final value\n   for their path expression\n - when this would create a cycle, when possible the cycle must be\n   broken by looking backward only (thus removing one of the\n   substitutions that's a link in the cycle)\n\nThe idea is to allow a new value for a field to be based on the\nolder value:\n\n```hocon\npath : \"a:b:c\"\npath : ${path}\":d\"\n```\n\nA _self-referential field_ is one which:\n\n - has a substitution, or value concatenation containing a\n   substitution, as its value\n - where this field value refers to the field being defined,\n   either directly or by referring to one or more other\n   substitutions which eventually point back to the field being\n   defined\n\nExamples of self-referential fields:\n\n - `a : ${a}`\n - `a : ${a}bc`\n - `path : ${path} [ /usr/bin ]`\n\nNote that an object or array with a substitution inside it is\n_not_ considered self-referential for this purpose. The\nself-referential rules do _not_ apply to:\n\n - `a : { b : ${a} }`\n - `a : [${a}]`\n\nThese cases are unbreakable cycles that generate an error. (If\n\"looking backward\" were allowed for these, something like\n`a={ x : 42, y : ${a.x} }` would look backward for a\nnonexistent `a` while resolving `${a.x}`.)\n\nA possible implementation is:\n\n - substitutions are resolved by looking up paths in a document.\n   Cycles only arise when the lookup document is an ancestor\n   node of the substitution node.\n - while resolving a potentially self-referential field (any\n   substitution or value concatenation that contains a\n   substitution), remove that field and all fields which override\n   it from the lookup document.\n\nThe simplest form of this implementation will report a circular\nreference as missing; in `a : ${a}` you would remove `a : ${a}`\nwhile resolving `${a}`, leaving an empty document to look up\n`${a}` in. You can give a more helpful error message if, rather\nthan simply removing the field, you leave a marker value\ndescribing the cycle. Then generate an error if you return to that\nmarker value during resolution.\n\nCycles should be treated the same as a missing value when\nresolving an optional substitution (i.e. the `${?foo}` syntax).\nIf `${?foo}` refers to itself then it's as if it referred to a\nnonexistent value.\n\n#### The `+=` field separator\n\nFields may have `+=` as a separator rather than `:` or `=`. A\nfield with `+=` transforms into a self-referential array\nconcatenation, like this:\n\n```hocon\na += b\n```\n\nbecomes:\n\n```hocon\na = ${?a} [b]\n```\n\n`+=` appends an element to a previous array. If the previous value\nwas not an array, an error will result just as it would in the\nlong form `a = ${?a} [b]`. Note that the previous value is\noptional (`${?a}` not `${a}`), which allows `a += b` to be the\nfirst mention of `a` in the file (it is not necessary to have `a =\n[]` first).\n\nNote: Akka 2.0 (and thus Play 2.0) contains an embedded\nimplementation of the config lib which does not support `+=`.\n\n#### Examples of Self-Referential Substitutions\n\nIn isolation (with no merges involved), a self-referential field\nis an error because the substitution cannot be resolved:\n\n```hocon\nfoo : ${foo} // an error\n```\n\nWhen `foo : ${foo}` is merged with an earlier value for `foo`,\nhowever, the substitution can be resolved to that earlier value.\nWhen merging two objects, the self-reference in the overriding\nfield refers to the overridden field. Say you have:\n\n```hocon\nfoo : { a : 1 }\n```\n\nand then:\n\n```hocon\nfoo : ${foo}\n```\n\nThen `${foo}` resolves to `{ a : 1 }`, the value of the overridden\nfield.\n\nIt would be an error if these two fields were reversed, so first:\n\n```hocon\nfoo : ${foo}\n```\n\nand then second:\n\n```hocon\nfoo : { a : 1 }\n```\n\nHere the `${foo}` self-reference comes before `foo` has a value,\nso it is undefined, exactly as if the substitution referenced a\npath not found in the document.\n\nBecause `foo : ${foo}` conceptually looks to previous definitions\nof `foo` for a value, the error should be treated as \"undefined\"\nrather than \"intractable cycle\"; as a result, the optional\nsubstitution syntax `${?foo}` does not create a cycle:\n\n```hocon\nfoo : ${?foo} // this field just disappears silently\n```\n\nIf a substitution is hidden by a value that could not be merged\nwith it (by a non-object value) then it is never evaluated and no\nerror will be reported. So for example:\n\n```hocon\nfoo : ${does-not-exist}\nfoo : 42\n```\n\nIn this case, no matter what `${does-not-exist}` resolves to, we\nknow `foo` is `42`, so `${does-not-exist}` is never evaluated and\nthere is no error. The same is true for cycles like `foo : ${foo},\nfoo : 42`, where the initial self-reference must simply be ignored.\n\nA self-reference resolves to the value \"below\" even if it's part\nof a path expression. So for example:\n\n```hocon\nfoo : { a : { c : 1 } }\nfoo : ${foo.a}\nfoo : { a : 2 }\n```\n\nHere, `${foo.a}` would refer to `{ c : 1 }` rather than `2` and so\nthe final merge would be `{ a : 2, c : 1 }`.\n\nRecall that for a field to be self-referential, it must have a\nsubstitution or value concatenation as its value. If a field has\nan object or array value, for example, then it is not\nself-referential even if there is a reference to the field itself\ninside that object or array.\n\nImplementations must be careful to allow objects to refer to paths\nwithin themselves, for example:\n\n```hocon\nbar : { foo : 42,\n        baz : ${bar.foo}\n      }\n```\n\nHere, if an implementation resolved all substitutions in `bar` as\npart of resolving the substitution `${bar.foo}`, there would be a\ncycle. The implementation must only resolve the `foo` field in\n`bar`, rather than recursing the entire `bar` object.\n\nBecause there is no inherent cycle here, the substitution must\n\"look forward\" (including looking at the field currently being\ndefined). To make this clearer, `bar.baz` would be `43` in:\n\n```hocon\nbar : { foo : 42,\n        baz : ${bar.foo}\n      }\nbar : { foo : 43 }\n```\n\nMutually-referring objects should also work, and are not\nself-referential (so they look forward):\n\n```hocon\n// bar.a should end up as 4\nbar : { a : ${foo.d}, b : 1 }\nbar.b = 3\n// foo.c should end up as 3\nfoo : { c : ${bar.b}, d : 2 }\nfoo.d = 4\n```\n\nAnother tricky case is an optional self-reference in a value\nconcatenation, in this example `a` should be `foo` not `foofoo`\nbecause the self reference has to \"look back\" to an undefined `a`:\n\n    a = ${?a}foo\n\nIn general, in resolving a substitution the implementation must:\n\n - lazy-evaluate the substitution target so there's no\n   \"circularity by side effect\"\n - \"look forward\" and use the final value for the path\n   specified in the substitution\n - if a cycle results, the implementation must \"look back\"\n   in the merge stack to try to resolve the cycle\n - if neither lazy evaluation nor \"looking only backward\" resolves\n   a cycle, the substitution is missing which is an error unless\n   the `${?foo}` optional-substitution syntax was used.\n\nFor example, this is not possible to resolve:\n\n```hocon\nbar : ${foo}\nfoo : ${bar}\n```\n\nA multi-step loop like this should also be detected as invalid:\n\n```hocon\na : ${b}\nb : ${c}\nc : ${a}\n```\n\nSome cases have undefined behavior because the behavior depends on\nthe order in which two fields are resolved, and that order is not\ndefined. For example:\n\n```hocon\na : 1\nb : 2\na : ${b}\nb : ${a}\n```\n\nImplementations are allowed to handle this by setting both `a` and\n`b` to 1, setting both to `2`, or generating an error. Ideally\nthis situation would generate an error, but that may be difficult\nto implement. Making the behavior defined would require always\nworking with ordered maps rather than unordered maps, which is too\nconstraining. Implementations only have to track order for\nduplicate instances of the same field (i.e. merges).\n\n## MIME Type\n\nUse \"application/hocon\" for Content-Type.\n\n## API Recommendations\n\nImplementations of HOCON ideally follow certain conventions and\nwork in a predictable way.\n\n### Automatic type conversions\n\nIf an application asks for a value with a particular type, the\nimplementation should attempt to convert types as follows:\n\n - number to string: convert the number into a string\n   representation that would be a valid number in JSON.\n - boolean to string: should become the string \"true\" or \"false\"\n - string to number: parse the number with the JSON rules\n - string to boolean: the strings \"true\", \"yes\", \"on\", \"false\",\n   \"no\", \"off\" should be converted to boolean values. It's\n   tempting to support a long list of other ways to write a\n   boolean, but for interoperability and keeping it simple, it's\n   recommended to stick to these six.\n - string to null: the string `\"null\"` should be converted to a\n   null value if the application specifically asks for a null\n   value, though there's probably no reason an app would do this.\n - numerically-indexed object to array: see the section\n   \"Conversion of numerically-indexed objects to arrays\" above\n\nThe following type conversions should NOT be performed:\n\n - null to anything: If the application asks for a specific type\n   and finds null instead, that should usually result in an error.\n - object to anything\n - array to anything\n - anything to object\n - anything to array, with the exception of numerically-indexed\n   object to array\n\nConverting objects and arrays to and from strings is tempting, but\nin practical situations raises thorny issues of quoting and\ndouble-escaping.\n\n### Units format\n\nImplementations may wish to support interpreting a value with some\nfamily of units, such as time units or memory size units: `10ms`\nor `512K`. HOCON does not have an extensible type system and there\nis no way to add a \"duration\" type. However, for example, if an\napplication asks for milliseconds, the implementation can try to\ninterpret a value as a milliseconds value.\n\nIf an API supports this, for each family of units it should define\na default unit in the family. For example, the family of duration\nunits might default to milliseconds (see below for details on\ndurations). The implementation should then interpret values as\nfollows:\n\n - if the value is a number, it is taken to be a number in\n   the default unit.\n - if the value is a string, it is taken to be this sequence:\n\n     - optional whitespace\n     - a number\n     - optional whitespace\n     - an optional unit name consisting only of letters (letters\n       are the Unicode `L*` categories, Java `isLetter()`)\n     - optional whitespace\n\n   If a string value has no unit name, then it should be\n   interpreted with the default unit, as if it were a number. If a\n   string value has a unit name, that name of course specifies the\n   value's interpretation.\n\n### Duration format\n\nImplementations may wish to support a `getMilliseconds()` (and\nsimilar for other time units).\n\nThis can use the general \"units format\" described above; bare\nnumbers are taken to be in milliseconds already, while strings are\nparsed as a number plus an optional unit string.\n\nThe supported unit strings for duration are case sensitive and\nmust be lowercase. Exactly these strings are supported:\n\n - `ns`, `nanosecond`, `nanoseconds`\n - `us`, `microsecond`, `microseconds`\n - `ms`, `millisecond`, `milliseconds`\n - `s`, `second`, `seconds`\n - `m`, `minute`, `minutes`\n - `h`, `hour`, `hours`\n - `d`, `day`, `days`\n\n### Size in bytes format\n\nImplementations may wish to support a `getBytes()` returning a\nsize in bytes.\n\nThis can use the general \"units format\" described above; bare\nnumbers are taken to be in bytes already, while strings are\nparsed as a number plus an optional unit string.\n\nThe one-letter unit strings may be uppercase (note: duration units\nare always lowercase, so this convention is specific to size\nunits).\n\nThere is an unfortunate nightmare with size-in-bytes units, that\nthey may be in powers or two or powers of ten. The approach\ndefined by standards bodies appears to differ from common usage,\nsuch that following the standard leads to people being confused.\nWorse, common usage varies based on whether people are talking\nabout RAM or disk sizes, and various existing operating systems\nand apps do all kinds of different things.  See\nhttp://en.wikipedia.org/wiki/Binary_prefix#Deviation_between_powers_of_1024_and_powers_of_1000\nfor examples. It appears impossible to sort this out without\ncausing confusion for someone sometime.\n\nFor single bytes, exactly these strings are supported:\n\n - `B`, `b`, `byte`, `bytes`\n\nFor powers of ten, exactly these strings are supported:\n\n - `kB`, `kilobyte`, `kilobytes`\n - `MB`, `megabyte`, `megabytes`\n - `GB`, `gigabyte`, `gigabytes`\n - `TB`, `terabyte`, `terabytes`\n - `PB`, `petabyte`, `petabytes`\n - `EB`, `exabyte`, `exabytes`\n - `ZB`, `zettabyte`, `zettabytes`\n - `YB`, `yottabyte`, `yottabytes`\n\nFor powers of two, exactly these strings are supported:\n\n - `K`, `k`, `Ki`, `KiB`, `kibibyte`, `kibibytes`\n - `M`, `m`, `Mi`, `MiB`, `mebibyte`, `mebibytes`\n - `G`, `g`, `Gi`, `GiB`, `gibibyte`, `gibibytes`\n - `T`, `t`, `Ti`, `TiB`, `tebibyte`, `tebibytes`\n - `P`, `p`, `Pi`, `PiB`, `pebibyte`, `pebibytes`\n - `E`, `e`, `Ei`, `EiB`, `exbibyte`, `exbibytes`\n - `Z`, `z`, `Zi`, `ZiB`, `zebibyte`, `zebibytes`\n - `Y`, `y`, `Yi`, `YiB`, `yobibyte`, `yobibytes`\n\nIt's very unclear which units the single-character abbreviations\n(\"128K\") should go with; some precedents such as `java -Xmx 2G`\nand the GNU tools such as `ls` map these to powers of two, so this\nspec copies that. You can certainly find examples of mapping these\nto powers of ten, though. If you don't like ambiguity, don't use\nthe single-letter abbreviations.\n\n### Config object merging and file merging\n\nIt may be useful to offer a method to merge two objects. If such a\nmethod is provided, it should work as if the two objects were\nduplicate values for the same key in the same file. (See the\nsection earlier on duplicate key handling.)\n\nAs with duplicate keys, an intermediate non-object value \"hides\"\nearlier object values. So say you merge three objects in this\norder:\n\n - `{ a : { x : 1 } }`  (first priority)\n - `{ a : 42 }` (fallback)\n - `{ a : { y : 2 } }` (another fallback)\n\nThe result would be `{ a : { x : 1 } }`. The two objects are not\nmerged because they are not \"adjacent\"; the merging is done in\npairs, and when `42` is paired with `{ y : 2 }`, `42` simply wins\nand loses all information about what it overrode.\n\nBut if you re-ordered like this:\n\n - `{ a : { x : 1 } }`  (first priority)\n - `{ a : { y : 2 } }` (fallback)\n - `{ a : 42 }` (another fallback)\n\nNow the result would be `{ a : { x : 1, y : 2 } }` because the two\nobjects are adjacent.\n\nThis rule for merging objects loaded from different files is\n_exactly_ the same behavior as for merging duplicate fields in the\nsame file. All merging works the same way.\n\nNeedless to say, normally it's well-defined whether a config\nsetting is supposed to be a number or an object. This kind of\nweird pathology where the two are mixed should not be happening.\n\nThe one place where it matters, though, is that it allows you to\n\"clear\" an object and start over by setting it to null and then\nsetting it back to a new object. So this behavior gives people a\nway to get rid of default fallback values they don't want.\n\n### hyphen-separated vs. camelCase\n\nConfig keys are encouraged to be `hyphen-separated` rather than\n`camelCase`.\n\n# Hocon.Extensions.Configuration\n`Hocon.Extensions.Configuration` is an extension of HOCON that\nallows HOCON configuration files to be read and loaded into `Microsoft.Extensions.Configuration`\n\n## Installation\nTo install [`Microsoft.Extensions.Configuration` via NuGet](https://www.nuget.org/packages/Hocon.Extensions.Configuration/):\n\n```\nPS\u003e Install-Package Hocon.Extensions.Configuration\n```\n\n## Examples\nAn example project on how to use `Hocon.Extensions.Configuration` with ASP.NET Core\nWeb Application can be seen [in the examples folder](https://github.com/akkadotnet/HOCON/tree/dev/src/examples/AspNetWebApp)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakkadotnet%2Fhocon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fakkadotnet%2Fhocon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakkadotnet%2Fhocon/lists"}