Class ConfigFile
In-memory representation of a grouped JSON configuration file used by the Scylla framework's
layered configuration system. A ConfigFile organizes its data as a flat collection of
named ConfigFileGroup instances, each containing an arbitrary number of
ConfigFileProperty values. Both groups and properties within each group are
stored in alphabetical order using case-insensitive key comparison.
Supports all primitive JSON types (boolean, integer, float, double, string), as well as
nested groups and ordered arrays. Colors are stored as ARGB hex strings (e.g. "#FF8040FF")
and can be read and written using TryGetColor(string, string, out Color) and SetColor(string, string, Color).
Provides serialization to and from human-readable, pretty-printed JSON via ToJSON() and FromJSON(string). Multiple files can be layered together using Merge(ConfigFile, ConfigFile), which combines a higher-priority file with a lower-priority one so that values from the lower file fill gaps not present in the higher file. This is the mechanism behind the four-tier override chain managed by ConfigFileManager.
Float and double values are rounded to six decimal places when serialized to JSON for human readability. NaN and infinity are preserved as-is.
Inherited Members
Namespace: Scylla.Core.Util.File
Assembly: ScyllaCore.dll
Syntax
public sealed class ConfigFile
Properties
GroupCount
Gets the total number of top-level groups currently registered in this config file. Each group corresponds to one JSON object key at the root level of the file.
Declaration
public int GroupCount { get; }
Property Value
| Type | Description |
|---|---|
| int |
Methods
AddGroup(string)
Creates and registers a new ConfigFileGroup with the given name. Unlike GetOrAddGroup(string), this method fails if a group with the same name already exists, making it suitable for scenarios where duplicate groups indicate a programming error. Group name comparison is case-insensitive.
Declaration
public ConfigFileGroup AddGroup(string groupName)
Parameters
| Type | Name | Description |
|---|---|---|
| string | groupName | The name of the new group. Must not be |
Returns
| Type | Description |
|---|---|
| ConfigFileGroup | The newly created and registered ConfigFileGroup. |
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException | Thrown if |
| InvalidOperationException | Thrown if a group with the same name (case-insensitive) already exists. |
FromJSON(string)
Deserializes a JSON string into a new ConfigFile instance.
The JSON is expected to describe a top-level object whose keys are group names, each
mapping to a nested object of property key/value pairs. Property values may be booleans,
integers, floats, strings, null, nested objects (parsed as sub-groups), or arrays.
Integer values that fall outside the Int32 range are automatically widened to
Double and a warning is logged via
LogCategory.Core. Property types not supported by the config format are skipped
with a warning rather than causing a hard failure.
Declaration
public static ConfigFile FromJSON(string json)
Parameters
| Type | Name | Description |
|---|---|---|
| string | json | The JSON string to parse. If |
Returns
| Type | Description |
|---|---|
| ConfigFile | A fully populated ConfigFile on success, or |
GetGroup(string)
Retrieves the ConfigFileGroup with the specified name.
Group name lookup is case-insensitive. Returns null without throwing if the
group does not exist or if groupName is null or empty.
Use HasGroup(string) to distinguish between a missing group and a null name.
Declaration
public ConfigFileGroup GetGroup(string groupName)
Parameters
| Type | Name | Description |
|---|---|---|
| string | groupName | The name of the group to retrieve. Comparison is case-insensitive. |
Returns
| Type | Description |
|---|---|
| ConfigFileGroup | The matching ConfigFileGroup instance, or |
GetGroupNames()
Returns a read-only view of all group names registered in this config file, enumerated in case-insensitive alphabetical order. The returned collection is backed by the internal dictionary's key set and involves no extra allocation. The collection is valid only as long as no groups are added or removed.
Declaration
public IReadOnlyCollection<string> GetGroupNames()
Returns
| Type | Description |
|---|---|
| IReadOnlyCollection<string> | A IReadOnlyCollection<T> of group name strings in alphabetical order. The collection is empty if no groups have been added. |
GetOrAddGroup(string)
Returns the existing ConfigFileGroup with the given name, or creates and registers a new empty group if one does not already exist. Group name lookup is case-insensitive. This is the preferred method for writing operations that should not fail if the group is missing.
Declaration
public ConfigFileGroup GetOrAddGroup(string groupName)
Parameters
| Type | Name | Description |
|---|---|---|
| string | groupName | The name of the group to retrieve or create. Must not be |
Returns
| Type | Description |
|---|---|
| ConfigFileGroup | The existing or newly created ConfigFileGroup. |
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException | Thrown if |
HasGroup(string)
Determines whether a group with the specified name exists in this config file.
Group name comparison is case-insensitive. Returns false immediately if
groupName is null or empty.
Declaration
public bool HasGroup(string groupName)
Parameters
| Type | Name | Description |
|---|---|---|
| string | groupName | The group name to look up. Comparison is case-insensitive. |
Returns
| Type | Description |
|---|---|
| bool |
|
HasProperty(string, string)
Determines whether a property with the specified name exists in the specified group.
Returns false if the group itself does not exist. Both comparisons are
case-insensitive. This is a convenience shorthand for calling GetGroup(string)
followed by HasProperty(string).
Declaration
public bool HasProperty(string groupName, string propertyName)
Parameters
| Type | Name | Description |
|---|---|---|
| string | groupName | The name of the group to look up. Comparison is case-insensitive. |
| string | propertyName | The name of the property to check. Comparison is case-insensitive. |
Returns
| Type | Description |
|---|---|
| bool |
|
Merge(ConfigFile, ConfigFile)
Creates a new ConfigFile that merges higher and
lower, where values from the higher-priority file take precedence.
Merge rules applied per property:
-
If a property exists only in
higher, it is included as-is. -
If a property exists only in
lower, it is included as-is. - If both files contain a property with the same name and both values are of type Group, they are recursively deep-merged (higher wins for any leaf conflict).
- In all other cases (type mismatch, primitive, array), the higher-priority value wins.
All values are deep-cloned into the result so that neither input file is modified and the result is independent of both inputs. A maximum nesting depth of Scylla.Core.Util.File.ConfigFile.MAX_NESTING_DEPTH is enforced to prevent stack overflows from circular or pathologically deep group structures.
Declaration
public static ConfigFile Merge(ConfigFile higher, ConfigFile lower)
Parameters
| Type | Name | Description |
|---|---|---|
| ConfigFile | higher | The higher-priority config file whose values override the lower. May be |
| ConfigFile | lower | The lower-priority config file that provides fallback values. May be |
Returns
| Type | Description |
|---|---|
| ConfigFile | A new, independent ConfigFile containing the merged result,
or |
RemoveGroup(string)
Removes the group with the specified name from this config file, along with all of
its properties. Returns false without throwing if the group does not exist or
if groupName is null or empty.
Declaration
public bool RemoveGroup(string groupName)
Parameters
| Type | Name | Description |
|---|---|---|
| string | groupName | The name of the group to remove. Comparison is case-insensitive. |
Returns
| Type | Description |
|---|---|
| bool |
|
SetArray(string, string, List<ConfigFileProperty>)
Writes an ordered list of ConfigFileProperty values as an array property
in the specified group. A shallow defensive copy of items is made
internally, so subsequent changes to the original list will not affect the stored value.
However, if any element is of type Group, the
underlying ConfigFileGroup instances are shared by reference. The
top-level group is created automatically if it does not already exist.
Declaration
public void SetArray(string groupName, string propertyName, List<ConfigFileProperty> items)
Parameters
| Type | Name | Description |
|---|---|---|
| string | groupName | The name of the target group. Created automatically if absent. Must not be |
| string | propertyName | The name of the property to write. Must not be |
| List<ConfigFileProperty> | items | The list of values to store as an array. Must not be |
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException | Thrown if |
SetBool(string, string, bool)
Writes a boolean property into the specified group, creating the group if it does not already exist. Overwrites any existing property with the same name regardless of its previous type.
Declaration
public void SetBool(string groupName, string propertyName, bool value)
Parameters
| Type | Name | Description |
|---|---|---|
| string | groupName | The name of the target group. Created automatically if absent. Must not be |
| string | propertyName | The name of the property to write. Must not be |
| bool | value | The boolean value to store. |
SetColor(string, string, Color)
Writes a UnityEngine.Color into the specified group as an 8-digit uppercase ARGB
hex string of the form "#AARRGGBB" (e.g. "#FF8040FF"). Each channel is
clamped to [0, 1] before conversion to avoid out-of-range byte values. The
resulting string can be recovered with TryGetColor(string, string, out Color). The group is created
automatically if it does not already exist.
Declaration
public void SetColor(string groupName, string propertyName, Color value)
Parameters
| Type | Name | Description |
|---|---|---|
| string | groupName | The name of the target group. Created automatically if absent. Must not be |
| string | propertyName | The name of the property to write. Must not be |
| Color | value | The color to store. All channels are clamped to |
SetDouble(string, string, double)
Writes a double-precision floating-point property into the specified group, creating the group if it does not already exist. Overwrites any existing property with the same name regardless of its previous type. When serialized via ToJSON(), double values are rounded to six decimal places for readability (NaN and infinity are preserved as-is).
Declaration
public void SetDouble(string groupName, string propertyName, double value)
Parameters
| Type | Name | Description |
|---|---|---|
| string | groupName | The name of the target group. Created automatically if absent. Must not be |
| string | propertyName | The name of the property to write. Must not be |
| double | value | The double value to store. |
SetFloat(string, string, float)
Writes a single-precision floating-point property into the specified group, creating the group if it does not already exist. Overwrites any existing property with the same name regardless of its previous type. When serialized via ToJSON(), float values are rounded to six decimal places for readability (NaN and infinity are preserved as-is).
Declaration
public void SetFloat(string groupName, string propertyName, float value)
Parameters
| Type | Name | Description |
|---|---|---|
| string | groupName | The name of the target group. Created automatically if absent. Must not be |
| string | propertyName | The name of the property to write. Must not be |
| float | value | The float value to store. |
SetGroup(string, string, ConfigFileGroup)
Writes a nested ConfigFileGroup as a property value in the specified top-level group. The sub-group reference is stored directly without defensive copying; callers are responsible for not mutating the group after storing it, or for providing a cloned copy. The top-level group is created automatically if it does not already exist.
Declaration
public void SetGroup(string groupName, string propertyName, ConfigFileGroup subGroup)
Parameters
| Type | Name | Description |
|---|---|---|
| string | groupName | The name of the top-level group that will contain the property. Created automatically
if absent. Must not be |
| string | propertyName | The name of the property to write. Must not be |
| ConfigFileGroup | subGroup | The nested group to store as the property value. Must not be |
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException | Thrown if |
SetInt(string, string, int)
Writes a 32-bit signed integer property into the specified group, creating the group if it does not already exist. Overwrites any existing property with the same name regardless of its previous type.
Declaration
public void SetInt(string groupName, string propertyName, int value)
Parameters
| Type | Name | Description |
|---|---|---|
| string | groupName | The name of the target group. Created automatically if absent. Must not be |
| string | propertyName | The name of the property to write. Must not be |
| int | value | The integer value to store. |
SetList<T>(string, string, IReadOnlyList<T>, Func<T, int, ConfigFileGroup>)
Sets a list of items as an array of Group elements in the specified group. Each item is converted to a ConfigFileGroup via the provided delegate. Null items in the list are skipped. A null or empty list writes an empty array.
This is a serialization helper that converts typed lists to internal Group arrays. For raw array manipulation, use SetArray(string, string, List<ConfigFileProperty>) / TryGetArray(string, string, out IReadOnlyList<ConfigFileProperty>).
Declaration
public void SetList<T>(string groupName, string propertyName, IReadOnlyList<T> items, Func<T, int, ConfigFileGroup> toGroup)
Parameters
| Type | Name | Description |
|---|---|---|
| string | groupName | The group name. |
| string | propertyName | The property name. |
| IReadOnlyList<T> | items | The list of items to serialize. Can be null or empty. |
| Func<T, int, ConfigFileGroup> | toGroup | A delegate that converts an item to a ConfigFileGroup.
The second parameter is the zero-based index of the item in the source list,
which can be used for naming (e.g., |
Type Parameters
| Name | Description |
|---|---|
| T | The item type. |
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException | Thrown if |
| ArgumentException | Thrown if the |
SetString(string, string, string)
Writes a string property into the specified group, creating the group if it does not
already exist. Overwrites any existing property with the same name regardless of its
previous type. A null value is valid and will be serialized as JSON null.
Declaration
public void SetString(string groupName, string propertyName, string value)
Parameters
| Type | Name | Description |
|---|---|---|
| string | groupName | The name of the target group. Created automatically if absent. Must not be |
| string | propertyName | The name of the property to write. Must not be |
| string | value | The string value to store. May be |
ToJSON()
Serializes this config file to a human-readable, pretty-printed JSON string suitable for writing to disk. Groups and properties within each group are written in case-insensitive alphabetical key order. Numeric float and double values are rounded to six decimal places; NaN and infinity are preserved using their JSON-writer representations. Nested groups are emitted as JSON sub-objects; arrays are emitted as JSON arrays. The resulting string can be deserialized back via FromJSON(string).
Declaration
public string ToJSON()
Returns
| Type | Description |
|---|---|
| string | A non-null pretty-printed JSON string representing the full contents of this config file.
Returns an empty JSON object ( |
TryGetArray(string, string, out IReadOnlyList<ConfigFileProperty>)
Attempts to read an array property from the specified group, returning the stored
list as a read-only view without cloning. Returns false without throwing if the
group does not exist, the property does not exist, or the property is not of type
Array.
Declaration
public bool TryGetArray(string groupName, string propertyName, out IReadOnlyList<ConfigFileProperty> items)
Parameters
| Type | Name | Description |
|---|---|---|
| string | groupName | The name of the group containing the property. Comparison is case-insensitive. |
| string | propertyName | The name of the property to read. Comparison is case-insensitive. |
| IReadOnlyList<ConfigFileProperty> | items | When this method returns |
Returns
| Type | Description |
|---|---|
| bool |
|
TryGetBool(string, string, out bool)
Attempts to read a boolean property from the specified group. Returns false
without throwing if the group or property does not exist, or if the stored value is
not of type Bool. No type coercion is performed.
Declaration
public bool TryGetBool(string groupName, string propertyName, out bool value)
Parameters
| Type | Name | Description |
|---|---|---|
| string | groupName | The name of the group containing the property. Comparison is case-insensitive. |
| string | propertyName | The name of the property to read. Comparison is case-insensitive. |
| bool | value | When this method returns |
Returns
| Type | Description |
|---|---|
| bool |
|
TryGetColor(string, string, out Color)
Attempts to read a UnityEngine.Color from a string property in the specified group.
Colors are expected to be stored as uppercase hexadecimal strings in ARGB format
(e.g. "#FF8040FF"), which is the format produced by SetColor(string, string, Color).
A six-digit RGB format (e.g. "#8040FF") is also accepted and treated as fully
opaque (alpha = 1). The leading # is optional. Returns false without
throwing if the property is missing, is not a string, is empty, or contains invalid
hex characters.
Declaration
public bool TryGetColor(string groupName, string propertyName, out Color value)
Parameters
| Type | Name | Description |
|---|---|---|
| string | groupName | The name of the group containing the property. Comparison is case-insensitive. |
| string | propertyName | The name of the property to read. Comparison is case-insensitive. |
| Color | value | When this method returns |
Returns
| Type | Description |
|---|---|
| bool |
|
TryGetDouble(string, string, out double)
Attempts to read a double-precision floating-point value from the specified group, accepting any compatible numeric property type. The following conversions are performed silently:
- Double - returned directly.
-
Float - widened to
doublevia implicit conversion; no precision is lost relative to the stored float. -
Int - widened to
doublevia implicit conversion; allInt32values are representable exactly.
No coercion is attempted for non-numeric types (Bool, String, Group, Array).
Declaration
public bool TryGetDouble(string groupName, string propertyName, out double value)
Parameters
| Type | Name | Description |
|---|---|---|
| string | groupName | The name of the group containing the property. Comparison is case-insensitive. |
| string | propertyName | The name of the property to read. Comparison is case-insensitive. |
| double | value | When this method returns |
Returns
| Type | Description |
|---|---|
| bool |
|
TryGetFloat(string, string, out float)
Attempts to read a single-precision floating-point value from the specified group, accepting any compatible numeric property type. The following conversions are performed silently:
- Float - returned directly.
-
Double - narrowed to
floatvia an explicit cast; values outside thefloatrange saturate to infinity. -
Int - widened to
floatvia implicit conversion; large integers may lose precision.
No coercion is attempted for non-numeric types (Bool, String, Group, Array).
Declaration
public bool TryGetFloat(string groupName, string propertyName, out float value)
Parameters
| Type | Name | Description |
|---|---|---|
| string | groupName | The name of the group containing the property. Comparison is case-insensitive. |
| string | propertyName | The name of the property to read. Comparison is case-insensitive. |
| float | value | When this method returns |
Returns
| Type | Description |
|---|---|
| bool |
|
TryGetGroup(string, string, out ConfigFileGroup)
Attempts to read a nested ConfigFileGroup property from the specified
top-level group. Returns the stored reference directly without cloning; callers must
not assume exclusive ownership of the returned group. Returns false without
throwing if the top-level group does not exist, the property does not exist, or the
property is not of type Group.
Declaration
public bool TryGetGroup(string groupName, string propertyName, out ConfigFileGroup subGroup)
Parameters
| Type | Name | Description |
|---|---|---|
| string | groupName | The name of the top-level group to look up. Comparison is case-insensitive. |
| string | propertyName | The name of the property to read. Comparison is case-insensitive. |
| ConfigFileGroup | subGroup | When this method returns |
Returns
| Type | Description |
|---|---|
| bool |
|
TryGetInt(string, string, out int)
Attempts to read a 32-bit signed integer property from the specified group. Returns
false without throwing if the group or property does not exist, or if the stored
value is not exactly of type Int. No widening or
narrowing conversion is performed; use TryGetDouble(string, string, out double) if the stored value
may have been widened to Double during parsing (e.g. values outside Int32 range).
Declaration
public bool TryGetInt(string groupName, string propertyName, out int value)
Parameters
| Type | Name | Description |
|---|---|---|
| string | groupName | The name of the group containing the property. Comparison is case-insensitive. |
| string | propertyName | The name of the property to read. Comparison is case-insensitive. |
| int | value | When this method returns |
Returns
| Type | Description |
|---|---|
| bool |
|
TryGetList<T>(string, string, out List<T>, Func<ConfigFileGroup, T>)
Tries to get a list of items from a Group-typed array in the specified group.
Each Group element in the array is converted to T via the provided delegate.
Non-Group array elements and null delegate results are silently skipped.
This is a deserialization helper that converts internal Group arrays to typed lists. For raw array manipulation, use SetArray(string, string, List<ConfigFileProperty>) / TryGetArray(string, string, out IReadOnlyList<ConfigFileProperty>).
Declaration
public bool TryGetList<T>(string groupName, string propertyName, out List<T> items, Func<ConfigFileGroup, T> fromGroup)
Parameters
| Type | Name | Description |
|---|---|---|
| string | groupName | The group name. |
| string | propertyName | The property name. |
| List<T> | items | The deserialized list if the array was found; otherwise, null. |
| Func<ConfigFileGroup, T> | fromGroup | A delegate that converts a ConfigFileGroup to an item of type |
Returns
| Type | Description |
|---|---|
| bool | True if the array property was found; otherwise, false. |
Type Parameters
| Name | Description |
|---|---|
| T | The item type. |
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException | Thrown if |
TryGetString(string, string, out string)
Attempts to read a string property from the specified group. Returns false
without throwing if the group or property does not exist, or if the stored value is
not of type String. Note that a string property
may legitimately hold a null value (stored when a JSON null is encountered);
in that case this method returns true and sets value to null.
Declaration
public bool TryGetString(string groupName, string propertyName, out string value)
Parameters
| Type | Name | Description |
|---|---|---|
| string | groupName | The name of the group containing the property. Comparison is case-insensitive. |
| string | propertyName | The name of the property to read. Comparison is case-insensitive. |
| string | value | When this method returns |
Returns
| Type | Description |
|---|---|
| bool |
|