Reputation: 6888
I have this groovy program that creates a groovy configuration file, using a ConfigObject. Once the ConfigObject is set up, it is written to a file using:
myFile.withWriter {writer -> myConfigObject.writeTo(writer)}
This results in each property of the ConfigObject being written on a single line. So for instance a map will be printed as:
graphs=[["type":"std", "host":"localhost", "name":"cpurawlinux"], ["type":"std", "host":"localhost", "name":"memory"], ["type":"std", "host":"localhost", "name":"udp"] ... ]
which is quite unreadable if someone has to take a look at it. Is there a way to get a more friendly output? Something like that would be great:
graphs=[
["type":"std", "host":"localhost", "name":"cpurawlinux"],
["type":"std", "host":"localhost", "name":"memory"],
["type":"std", "host":"localhost", "name":"udp"]
...
]
I know I could create my own writeTo
, but isn't there already something in Groovy for that?
Upvotes: 5
Views: 5903
Reputation: 61
Since GreenGiant answer seems broken when I tried using it, here's a working version for future reference :
static String prettify(obj, level = 0, StringBuilder sb = new StringBuilder()) {
def indent = { lev -> sb.append(" " * lev) }
if (!obj) return sb
if(obj instanceof Map<String, ?>){
sb.append("{\n")
obj.each{ name, value ->
if(name.contains('.')) return // skip keys like "a.b.c", which are redundant
indent(level+1).append(name)
(value instanceof Map) ? sb.append(" ") : sb.append(" = ")
prettify(value, level+1, sb)
sb.append("\n")
}
indent(level).append("}")
} else if(obj instanceof List){
sb.append("[\n")
obj.each{ value ->
indent(level+1)
prettify(value, level+1, sb).append(",")
sb.append("\n")
}
indent(level).append("]")
} else if(obj instanceof String){
sb.append('"').append(obj).append('"')
} else {
sb.append(obj)
}
}
Upvotes: 1
Reputation: 5256
Based on mike's answer above:
def prettyPrint
prettyPrint = {obj, level = 0, sb = new StringBuilder() ->
def indent = { lev -> sb.append(" " * lev) }
if(obj instanceof Map){
sb.append("{\n")
obj.each{ name, value ->
if(name.contains('.')) return // skip keys like "a.b.c", which are redundant
indent(level+1).append(name)
(value instanceof Map) ? sb.append(" ") : sb.append(" = ")
prettyPrint(value, level+1, sb)
sb.append("\n")
}
indent(level).append("}")
}
else if(obj instanceof List){
sb.append("[\n")
obj.each{ value ->
indent(level+1)
prettyPrint(value, level+1, sb).append(",")
sb.append("\n")
}
indent(level).append("]")
}
else if(obj instanceof String){
sb.append('"').append(obj).append('"')
}
else {
sb.append(obj)
}
}
For an input like:
{
grails {
scaffolding {
templates.domainSuffix = "Instance"
}
enable {
native2ascii = true
blah = [ 1, 2, 3 ]
}
mime.disable.accept.header.userAgents = [ "WebKit", "Presto", "Trident" ]
}
}
Produces:
{
grails {
scaffolding {
templates {
domainSuffix = "Instance"
}
}
enable {
native2ascii = true
blah = [
1,
2,
3,
]
}
mime {
disable {
accept {
header {
userAgents = [
"WebKit",
"Presto",
"Trident",
]
}
}
}
}
}
}
Upvotes: 1
Reputation: 514
if it helps anyone, i had the same question and wrote this...not pretty (ha), but works:
def prettyPrint(properties, level=1, stringBuilder = new StringBuilder()) {
return properties.inject(stringBuilder) { sb, name, value ->
sb.append("\n").append("\t" * level).append(name)
if (!(value instanceof Map) && !(value instanceof List)) {
return sb.append("=").append(value)
} else {
return prettyPrint(properties.getProperty(name), level+1, sb)
}
}
}
Upvotes: 1
Reputation: 171144
Unfortunately, you'll need to write your own writeTo
as you say.
If you have a config file with structure like:
graphs {
a=["type":"std", "host":"localhost", "name":"cpurawlinux"]
b=["type":"std", "host":"localhost", "name":"memory"]
}
Then writeTo will write it out with structure, but if your config file is just a big old list of things, it will write it out as a big old list
Upvotes: 1