SkillAgentSearch skills...

HOCON

C# implementation of Lightbend's HOCON (Human-Optimized Object Configuration Notation)

Install / Use

/learn @akkadotnet/HOCON
About this skill

Quality Score

0/100

Supported Platforms

Zed

README

HOCON (Human-Optimized Config Object Notation)

C# implementation of Typesafe's HOCON (Human-Optimized Object Configuration Notation)

Installation

To install HOCON via NuGet:

PS> Install-Package Hocon.Configuration

Nightly Build Access

If you need access to nightly HOCON builds, you can get them via the Akka.NET nightly build NuGet feed.

Spec

This is an informal spec, but hopefully it's clear.

Goals / Background

The primary goal is: keep the semantics (tree structure; set of types; encoding/escaping) from JSON (JavaScript Object Notation), but make it more convenient as a human-editable config file format.

The following features are desirable, to support human usage:

  • less noisy / less pedantic syntax
  • ability to refer to another part of the configuration (set a value to another value)
  • import/include another configuration file into the current file
  • a mapping to a flat properties list such as Java's system properties
  • ability to get values from environment variables
  • ability to write comments

Implementation-wise, the format should have these properties:

  • a JSON superset, that is, all valid JSON should be valid and should result in the same in-memory data that a JSON parser would have produced.
  • be deterministic; the format is flexible, but it is not heuristic. It should be clear what's invalid and invalid files should generate errors.
  • require minimal look-ahead; should be able to tokenize the file by looking at only the next three characters. (right now, the only reason to look at three is to find "//" comments; otherwise you can parse looking at two.)

HOCON is significantly harder to specify and to parse than JSON. Think of it as moving the work from the person maintaining the config file to the computer program.

Default HOCON Configuration Sources

By default the HOCON library will look for HOCON configurations in the following locations whenever you call the Hocon.Configuration.ConfigurationFactory.Default() method:

  1. [.NET Core / .NET Framework] An "app.conf" or an "app.hocon" file in the current working directory of the executable when it loads;
  2. [.NET Framework] - the <hocon> ConfigurationSection inside App.config or Web.config; or
  3. [.NET Framework] - and a legacy option, to load the old <akka> HOCON section for backwards compatibility purposes with all users who have been using HOCON with Akka.NET.

Definitions

  • a key is a string JSON would have to the left of : and a value is anything JSON would have to the right of :. i.e. the two halves of an object field.

  • a value is any "value" as defined in the JSON spec, plus unquoted strings and substitutions as defined in this spec.

  • a simple value is any value excluding an object or array value.

  • a field is a key, any separator such as ':', and a value.

  • references to a file ("the file being parsed") can be understood to mean any byte stream being parsed, not just literal files in a filesystem.

Syntax

Much of this is defined with reference to JSON; you can find the JSON spec at http://json.org/ of course.

Unchanged from JSON

  • files must be valid UTF-8
  • quoted strings are in the same format as JSON strings
  • values have possible types: string, number, object, array, boolean, null
  • allowed number formats matches JSON; as in JSON, some possible floating-point values are not represented, such as NaN

Comments

Anything between // or # and the next newline is considered a comment and ignored, unless the // or # is inside a quoted string.

Omit root braces

JSON documents must have an array or object at the root. Empty files are invalid documents, as are files containing only a non-array non-object value such as a string.

In HOCON, if the file does not begin with a square bracket or curly brace, it is parsed as if it were enclosed with {} curly braces.

A HOCON file is invalid if it omits the opening { but still has a closing }; the curly braces must be balanced.

Key-value separator

The = character can be used anywhere JSON allows :, i.e. to separate keys from values.

If a key is followed by {, the : or = may be omitted. So "foo" {} means "foo" : {}

Commas

Values in arrays, and fields in objects, need not have a comma between them as long as they have at least one ASCII newline (\n, decimal value 10) between them.

The last element in an array or last field in an object may be followed by a single comma. This extra comma is ignored.

  • [1,2,3,] and [1,2,3] are the same array.
  • [1\n2\n3] and [1,2,3] are the same array.
  • [1,2,3,,] is invalid because it has two trailing commas.
  • [,1,2,3] is invalid because it has an initial comma.
  • [1,,2,3] is invalid because it has two commas in a row.
  • these same comma rules apply to fields in objects.

Whitespace

The JSON spec simply says "whitespace"; in HOCON whitespace is defined as follows:

  • any Unicode space separator (Zs category), line separator (Zl category), or paragraph separator (Zp category), including nonbreaking spaces (such as 0x00A0, 0x2007, and 0x202F). The BOM (0xFEFF) must also be treated as whitespace.
  • tab (\t 0x0009), newline ('\n' 0x000A), vertical tab ('\v' 0x000B), form feed (\f' 0x000C), carriage return ('\r' 0x000D), file separator (0x001C), group separator (0x001D), record separator (0x001E), unit separator (0x001F).

In Java, the isWhitespace() method covers these characters with the exception of nonbreaking spaces and the BOM.

While all Unicode separators should be treated as whitespace, in this spec "newline" refers only and specifically to ASCII newline 0x000A.

Duplicate keys and object merging

The JSON spec does not clarify how duplicate keys in the same object should be handled. In HOCON, duplicate keys that appear later override those that appear earlier, unless both values are objects. If both values are objects, then the objects are merged.

Note: this would make HOCON a non-superset of JSON if you assume that JSON requires duplicate keys to have a behavior. The assumption here is that duplicate keys are invalid JSON.

To merge objects:

  • add fields present in only one of the two objects to the merged object.
  • for non-object-valued fields present in both objects, the field found in the second object must be used.
  • for object-valued fields present in both objects, the object values should be recursively merged according to these same rules.

Object merge can be prevented by setting the key to another value first. This is because merging is always done two values at a time; if you set a key to an object, a non-object, then an object, first the non-object falls back to the object (non-object always wins), and then the object falls back to the non-object (no merging, object is the new value). So the two objects never see each other.

These two are equivalent:

{
    "foo" : { "a" : 42 },
    "foo" : { "b" : 43 }
}

{
    "foo" : { "a" : 42, "b" : 43 }
}

And these two are equivalent:

{
    "foo" : { "a" : 42 },
    "foo" : null,
    "foo" : { "b" : 43 }
}

{
    "foo" : { "b" : 43 }
}

The intermediate setting of "foo" to null prevents the object merge.

Unquoted strings

A sequence of characters outside of a quoted string is a string value if:

  • it does not contain "forbidden characters": "$", '"', '{', '}', '[', ']', ':', '=', ',', '+', '#', '`', '^', '?', '!', '@', '*', '&', '' (backslash), or whitespace.
  • it does not contain the two-character string "//" (which starts a comment)
  • its initial characters do not parse as true, false, null, or a number.

Unquoted strings are used literally, they do not support any kind of escaping. Quoted strings may always be used as an alternative when you need to write a character that is not permitted in an unquoted string.

truefoo parses as the boolean token true followed by the unquoted string foo. However, footrue parses as the unquoted string footrue. Similarly, 10.0bar is the number 10.0 then the unquoted string bar but bar10.0 is the unquoted string bar10.0. (In practice, this distinction doesn't matter much because of value concatenation; see later section.)

In general, once an unquoted string begins, it continues until a forbidden character or the two-character string "//" is encountered. Embedded (non-initial) booleans, nulls, and numbers are not recognized as such, they are part of the string.

An unquoted string may not begin with the digits 0-9 or with a hyphen (-, 0x002D) because those are valid characters to begin a JSON number. The initial number character, plus any valid-in-JSON number characters that follow it, must be parsed as a number value. Again, these characters are not special inside an unquoted string; they only trigger number parsing if they appear initially.

Note that quoted JSON strings may not contain control characters (control characters include some whitespace characters, such as newline). This rule is from the JSON spec. However, unquoted strings have no restriction on control characters, other than the ones listed as "forbidden characters" above.

Some of the "forbidden characters" are forbidden because they already have meaning in JSON or HOCON, others are essentially reserved keywords to allow future extensions to this spec.

Multi-line strings

Multi-line strings are similar to Python or Scala, using triple quotes. If the three-character sequence """ appears, then all Unicode characters until a closing """ sequence are used unmodified to create a string value. Newlines and whitespace receive no special treatment. Unlike Scala, and unlike JSON quoted strings, Unicode escapes are not interpreted in trip

Related Skills

View on GitHub
GitHub Stars142
CategoryDevelopment
Updated2mo ago
Forks41

Languages

C#

Security Score

85/100

Audited on Jan 12, 2026

No findings