Builders

28.1 MarkupBuilder (XML/HTML)

StreamingMarkupBuilder for large documents (with namespaces and mkp.yieldUnescaped).

import groovy.xml.MarkupBuilder
def writer = new StringWriter()
def html = new MarkupBuilder(writer)
html.html {
    head { title "Groovy Builder" }
    body {
        h1 class: "title", "Welcome"
        ul {
            ['Ana', 'Bo'].each { name -> li name }
        }
        a href: "https://groovy-lang.org", "Groovy"
    }
}
println writer

28.2 JsonBuilder and StreamingJsonBuilder

import groovy.json.JsonBuilder
def json = new JsonBuilder()
json.person {
    name "Ana"
    age 30
    skills "Groovy", "Java"
    address(city: "Pune", zip: "411001")
}
println json.toPrettyString()
def list = new JsonBuilder([1, 2, 3])
def sw = new StringWriter()
new groovy.json.StreamingJsonBuilder(sw).users([[id: 1], [id: 2]])

28.3 Other Builders

Generic tree of Nodes Build object graphs (beans) Create directory/file structures SwingBuilder / groovy-swing Run Ant tasks (ant.copy(todir:...)) Command-line parsing (Module 38) YamlBuilder / TomlBuilder YAML / TOML (Groovy 3+/4+)

def tree = new FileTreeBuilder(new File("project"))
tree.dir("src") {
    dir("main") { file("App.groovy", "println 'hi'") }
    file("README.md") { withWriter('UTF-8') { it << "# Project" } }
}

def ant = new AntBuilder()
ant.zip(destfile: "out.zip", basedir: "project")

28.4 Writing Your Own Builder

Or use FactoryBuilderSupport for factories per node type. Simple builders can just use methodMissing + closures.

class HtmlBuilder extends BuilderSupport {
    def sb = new StringBuilder()
    protected void setParent(Object parent, Object child) {}
    protected Object createNode(Object name) { sb << "<$name>"; name }
    protected Object createNode(Object name, Object value) { sb << "<$name>$value"; name }
    protected Object createNode(Object name, Map attrs) { sb << "<$name ${attrs.collect { k, v -> "$k='$v'" }.join(' ')}>"; name }
    protected Object createNode(Object name, Map attrs, Object value) { createNode(name, attrs); sb << value; name }
    protected void nodeCompleted(Object parent, Object node) { sb << "</$node>" }
}
def b = new HtmlBuilder()
b.div(class: "box") { p "Hello" }
println b.sb