Repository navigation
Working With Comments
TOMLy can preserve and work with TOML comments, a unique feature among Java TOML libraries.
TOML supports single-line comments starting with #:
Comments appearing before a key-value pair or table:
# This is a header comment
# It can span multiple lines
name = "MyApp"Comments on the same line as a value:
name = "MyApp" # This is an inline comment
port = 8080 # Default portEmpty lines that separate values or sections:
name = "MyApp"
version = "1.0.0"
[server]
host = "localhost"PreserveOptions options = PreserveOptions.builder()
.preserveHeaderComments(true)
.preserveInlineComments(true)
.preserveBlankLines(true)
.build();
TomlDocument doc = Tomly.parse(toml, false, options);Comments are stored in Node objects:
String toml = """
# Application configuration
# Version 1.0
name = "MyApp" # The application name
version = "1.0.0"
""";
PreserveOptions options = PreserveOptions.builder()
.preserveHeaderComments(true)
.preserveInlineComments(true)
.build();
TomlDocument doc = Tomly.parse(toml, true, options);
Node nameNode = doc.get("name");
// Get header comments
List<String> headers = nameNode.headerComments();
// ["# Application configuration", "# Version 1.0"]
// Get inline comment
String inline = nameNode.inlineComment();
// "The application name"
// Get position
int line = nameNode.line(); // 3
int column = nameNode.column(); // 0With preserveBlankLines(), empty lines appear as empty strings:
PreserveOptions options = PreserveOptions.builder()
.preserveBlankLines(true)
.preserveHeaderComments(true)
.build();
String toml = """
# Comment
name = "value"
""";
TomlDocument doc = Tomly.parse(toml, true, options);
Node node = doc.get("name");
List<String> comments = node.headerComments();
// ["# Comment", ""]- Only consecutive comment lines are collected
- Blank lines break the sequence if preserveBlankLines is set to false
- Leading # is not removing
- All whitespaces after # in header comments is preserved
Example:
# Comment 1
# Comment 2
# Comment 3 (separate block)
name = "value"Node node = doc.get("name");
List<String> comments = node.headerComments();
// ["# Comment 1", "# Comment 2", "", "# Comment 3 (separate block)"]- Must be on the same line as the value
- Leading/trailing whitespace is trimmed
-
#character is removed
Example:
name = "value" # This is inline
port = 8080 #No leading space is still valid
count = 42#This works tooString comment1 = doc.get("name").inlineComment(); // "This is inline"
String comment2 = doc.get("port").inlineComment(); // "No leading space is still valid"
String comment3 = doc.get("count").inlineComment(); // "This works too"If there's no inline comment, returns null:
String toml = "name = \"value\"";
TomlDocument doc = Tomly.parse(toml, true, options);
String comment = doc.get("name").inlineComment(); // nullTables can also have comments:
# Server configuration
# Contains host and port settings
[server]
host = "localhost" # Default host
port = 8080Node serverNode = doc.get("server");
List<String> headers = serverNode.headerComments();
// [" Server configuration", " Contains host and port settings"]
TomlDocument server = doc.getSection("server");
Node hostNode = server.get("host");
String inline = hostNode.inlineComment(); // " Default host"Arrays but not their elements can have comments:
# List of servers
servers = [
"server1", # this will cause an exception
"server2",
"server3"
]Node serversNode = doc.get("servers");
List<String> arrayComments = serversNode.headerComments();
// [" List of servers"]When saving TOML, control comment output with WriterOptions:
WriterOptions options = WriterOptions.builder()
.writeHeaderComments(true)
.writeInlineComments(true)
.writeBlankLines(true)
.build();
doc.save(Path.of("output.toml"), options);Generate configuration with documentation:
// Create nodes with comments
StringNode appName = new StringNode(
"MyApp",
List.of("# Application name", "# Used in logs and UI"),
"Change with care"
);
doc.set("app.name", appName);
WriterOptions options = WriterOptions.builder()
.writeHeaderComments(true)
.writeInlineComments(true)
.build();
doc.save(Path.of("config.toml"), options);Output:
# Application name
# Used in logs and UI
[app]
name = "MyApp" # Change with carePreserve comments when updating config files:
PreserveOptions parseOpts = PreserveOptions.builder()
.preserveHeaderComments(true)
.preserveInlineComments(true)
.preserveBlankLines(true)
.build();
WriterOptions writeOpts = WriterOptions.builder()
.writeHeaderComments(true)
.writeInlineComments(true)
.writeBlankLines(true)
.build();
// Load with comments
TomlDocument doc = Tomly.parse(oldConfigPath, true, parseOpts);
// Update values
doc.set("version", new StringNode("2.0.0", List.of(), null));
// Save with comments preserved
doc.save(newConfigPath, writeOpts);Extract documentation from TOML files:
TomlDocument doc = Tomly.parse(configPath, true, options);
Map<String, Node> raw = doc.value();
for (Map.Entry<String, Node> entry : raw.entrySet()) {
Node node = entry.getValue();
List<String> docs = node.headerComments();
if (!docs.isEmpty()) {
System.out.println("Key: " + entry.getKey());
System.out.println("Documentation:");
docs.forEach(comment -> System.out.println(" " + comment.substring(1).trim()));
System.out.println();
}
}Create config templates with helpful comments:
public TomlDocument createTemplate() {
TomlDocument doc = new DocumentNode(new LinkedHashMap<>(), 1, 0, List.of(), null);
doc.set("app.name", new StringNode(
"MyApp",
List.of("# Application name"),
"required"
));
doc.set("app.version", new StringNode(
"1.0.0",
List.of("# Semantic version"),
"format: major.minor.patch"
));
doc.set("server.host", new StringNode(
"localhost",
List.of("# Server configuration", " Bind address"),
"use 0.0.0.0 for all interfaces"
));
doc.set("server.port", new NumberNode(
8080L,
1, 0,
List.of("# Port number"),
"1024-65535"
));
return doc;
}
TomlDocument template = createTemplate();
WriterOptions options = WriterOptions.builder()
.writeHeaderComments(true)
.writeInlineComments(true)
.writeBlankLines(true)
.build();
template.save(Path.of("config.template.toml"), options);Currently, individual array elements cannot have their own comments preserved:
servers = [
"server1", # This comment is lost
"server2" # This too
]Only the array itself can have comments:
# This comment is preserved
servers = ["server1", "server2"]Inline tables have limited comment support:
server = { host = "localhost", port = 8080 } # Only this is preservedIndividual fields in inline tables cannot have inline comments.
Recommendation: Use comment preservation only when needed (templates, documentation, config management).
- Enable only needed preservation: Don't enable preserveBlankLines if you don't need them
- Document your configuration: Use header comments for field documentation
- Keep inline comments short: They should fit on one line
- Use blank lines for grouping: Separate logical sections with blank lines
- Learn about Modifying And Saving to work with comments when writing
- See Configuration Options for all preservation settings