JSON as default preferences format
thekid opened this issue · 3 comments
Scope of Change
This RFC suggests replacing .ini with JSON as default preferences format
Rationale
Originally motivated by comparing .ini-file parsing performance to JSON decoding, after xp-framework/core#167 is merged, much of the disadvantage has been solved and it now boils down to readability.
Functionality
Comparison
[static]
resources=".css$:{DOCUMENT_ROOT}|^/image/:{DOCUMENT_ROOT}"
[app]
mappings[/rss]=rss
mappings[/]=dialog
[app::dialog]
init-params="de.thekid.dialog.scriptlet|{WEBROOT}/xsl"
[app::rss]
...
Although not as compact, the JSON syntax is standardized, can be syntax-checked, and pretty-printed using standard tooling. JSON also supports arbitrary nesting, so we could reimagine the above file in a much more concise way, and implement reading in an easier and faster way.
{
"static" : {
".css$" : "{DOCUMENT_ROOT}",
"^/image/" : "{DOCUMENT_ROOT}"
},
"app" : {
"/" : {
"init-params" : ["de.thekid.dialog.scriptlet", "{WEBROOT}/xsl"]
},
"/rss" : {
...
}
}
}
Example dialog.json
{
"database" : {
"dsn" : "mysql://…",
"create" : false
}
}
API
class util.Settings {
__construct(util.Config|util.PropertyAccess|string... $sources)
util.Setting named($path)
var value(string $path, var $default) throws util.NoSuchElementException
}
Examples
// Read from both ./dialog.json & ~/.xp/dialog.json & /etc/dialog.json
$settings= new Settings('preferences://dialog');
// Read from ./dialog.json, ~/.xp/dialog.json, /etc/dialog.json
$settings= new Settings('dialog');
$settings= new Settings('user://dialog');
$settings= new Settings('system://dialog');
// Reading from src/main/etc/dialog.json
$settings= new Settings('src/main/etc/dialog');
// Inheriting from user configuration
$settings= new Settings(new Config(Config::$USER, 'dialog'), new Config($path, 'dialog'));
// Accessing settings
$setting= $settings->named('database/dsn');
$setting->value(); // "mysql://…"
$setting->value('string'); // With primitive type
$setting->value(DSN::class); // With class type, calls "new"
$setting->present(); // true
$setting->orElse(null)->value(); // With default
// Access value directly, raises exception if not present
$conn= DriverManager::getConnection($settings->value('database/dsn'));
// Access with default
$create= $settings->value('database/create', false);
BC
For BC reasons, an adapter class for util.Properties
will be created.
Security considerations
Speed impact
Dependencies
Related documents
http://json.org/index.html - Introducing JSON
Hi,
since settings are written and maintained by humans i would strongly disagree with using JSON as the default. This is because JSON does not allow comments (you could use comment-elements...).
Tools exist to make it easier for humans, not the other way around.
I personally would suggest using/supporting YAML, if not already present.
my 2 cents
YAML means importing quite an extensive API (if you want to support all of it). Also, it is not natively supported by PHP - there is no yaml_parse()
in core.
But you're right, JSON has the problem of not offering comments, which are used quite often in INI files to explain options.
Maybe https://github.com/toml-lang/toml would be better: Like .ini, has comments, but supports nesting, dates and other handy features.
Maybe https://github.com/toml-lang/toml would be better
Yes.