Closed SackCastellon closed 6 years ago
I add support for config export/import in a new release, please check it in v0.7. Now items and associated values in config can be exported to a map, which can be (de)serialized in your favorite format by your favorite serialization library, and be imported into config in the next run. I also provide an example using Java Object Serialization to (de)serialize config (see config persistence). If you need more examples or integrated support (e.g. save/load config to/from YAML/JSON/XML/...), feel free to ask me. Feedback or advice is welcome.
It would be great if you could add support to save directly to JSON (for my case), or maybe provide me with an example of how to properly save to JSON because by default the format is not the right one and the workaround I found is not pretty, I would say.
object server : ConfigSpec("server") {
val port = optional("port", 3306, "The port of the server")
val host = required<String>("host", "The host IP of the server")
val database = required<String>("database", "The name of the database in the server")
}
object login : ConfigSpec("login") {
val rememberUsername = optional("rememberUsername", false, "Will the last input username be remembered?")
val username = optional("username", "", "The last input username")
}
val config = Config { addSpec(server);addSpec(login); }.withSourceFrom.json.resource("original.json")
{
"server": {
"host": "example.com",
"database": "database"
},
"login": {
"rememberUsername": false
}
}
fun main(args: Array<String>) {
FileWriter("output.json").use {
GsonBuilder().create().toJson(config.toMap(), it)
}
}
{
"server.port": 3306,
"server.host": "example.com",
"server.database": "database",
"login.rememberUsername": false,
"login.username": ""
}
{
"server": {
"host": "example.com",
"database": "database"
},
"login": {
"rememberUsername": false
}
}
fun main(args: Array<String>) {
val mapToExport = mutableMapOf<String, Any>()
for (it in config.toTree().items) {
if (it is OptionalItem)
if (config[it] == it.default)
continue // Skip if the item is optional and the value is the default
var map = mapToExport
it.path.dropLast(1).forEach {
val tmp: MutableMap<String, Any> =
if (map.contains(it)) map[it] as MutableMap<String, Any>
else mutableMapOf()
map.put(it, tmp) // Create the path with maps of maps
map = tmp
}
map.put(it.path.last(), config[it]) // Put the value of the item in the map (of maps)
}
FileWriter("output.json").use {
GsonBuilder().create().toJson(mapToExport, it)
}
}
{
"server": {
"host": "example.com",
"database": "database"
}
}
@SackCastellon I guess you want to merge all updates to config with the original config file and save it as exactly the same format with the original config file. Am I right?
@SackCastellon Further question: which of the following ones is your preferred use case:
@uchuhimo
I guess you want to merge all updates to config with the original config file and save it as exactly the same format with the original config file. Am I right?
Yes
Further question: which of the following ones is your preferred use case:
- write back all updates to the original config file when exiting
- write through all updates to the original config file (keep synchronous between config and its source)
- save all updates to somewhere in certain format for recovering or debugging
Number 2, as soon as a value is updated write it to the config file
@SackCastellon Konf is not designed for keeping synchronous between config and its source. In essence, Konf is an aggregator to collect config from different sources using schema defined by ConfigSpec
, instead of a view of its sources. Thus, supporting use case 2 is not in my future plan for Konf. But I will try my best to satisfy your requirement by providing support for use case 1. I have added a new Writer API to export config to various output format, and JSON writer support is in the master branch now. In your use case, you can use the following code to write back all updates to JSON config file when exiting:
config.layer.toJson.toFile(file)
Use master snapshot of Konf to test this new feature. I will add these APIs to next release after a full test. Feedback is welcome if any bug is found.
@uchuhimo There is a problem with the kotlinx-bimap dependency, the master snapshot of Konf is looking for version 0.7
But the latest version in your GitHub is 1.0
@SackCastellon Sorry for not testing master snapshot from JitPack in advance. It seems like a bug of JitPack , and I have found a workaround for it. Please refresh your dependencies (use ./gradlew build --refresh-dependencies
) and try again.
@uchuhimo So far it works well. 👍 If I find any bug I'll let you know
I will close this issue. You can open new issue or reopen this issue if any bug is found.
The new Writer API has been fully tested. I release it in v0.8 and publish to JCenter.
Is there any way to save the changed values to the same file from which the values were loaded, so when the program is run a second time then the new values are loaded?