Repository navigation
Modifying And Saving
GroundbreakingMC edited this page Oct 3, 2025
·
1 revision
Learn how to modify TOML documents and save them back to files.
First, load an existing TOML file:
Path configPath = Path.of("config.toml");
TomlDocument doc = Tomly.parse(configPath, false, PreserveOptions.defaultOptions());The set() method adds or updates values:
// Simple string value
doc.set("app.name", new StringNode("NewApp", List.of(), null));
// Number value
doc.set("server.port", new NumberNode(9090L, List.of(), null));
// Boolean value
doc.set("app.debug", new BooleanNode(true, List.of(), null));Each Node type has a constructor:
// StringNode(value, headerComments, inlineComment)
StringNode stringNode = new StringNode("value", List.of(), null);
// NumberNode(value, headerComments, inlineComment)
NumberNode numberNode = new NumberNode(42L, List.of(), null);
// BooleanNode(value, headerComments, inlineComment)
BooleanNode boolNode = new BooleanNode(true, List.of(), null);
// ArrayNode(value, headerComments, inlineComment)
List<Node> nodeArray = List.of(new StringNode("value", List.of(), null));
ArrayNode boolNode = new ArrayNode(nodeArray, List.of(), null);
// DatetimeNode(value, headerComments, inlineComment)
DatetimeNode dateNode = new DatetimeNode(
LocalDate.now(), List.of(), null
);Line and column are used for error reporting and can be set to any value (commonly 1, 0).
Include comments when creating nodes:
StringNode withComments = new StringNode(
"MyApp",
List.of("# Application name", "# Required field"), // Header comments
"Do not change" // Inline comment
);
doc.set("name", withComments);Use dot notation to set nested values:
// Creates or updates server.host
doc.set("server.host", new StringNode("192.168.1.10", List.of(), null));
// Creates or updates database.connection.timeout
doc.set("database.connection.timeout", new NumberNode(30L, 1, 0, List.of(), null));import com.github.groundbreakingmc.tomly.nodes.impl.ArrayNode;
// Create array of strings
List<Node> serverNodes = List.of(
new StringNode("server1", List.of(), null),
new StringNode("server2", List.of(), null),
new StringNode("server3", List.of(), null)
);
ArrayNode serversArray = new ArrayNode(serverNodes, List.of(), null);
doc.set("servers", serversArray);Output:
servers = ["server1", "server2", "server3"]import com.github.groundbreakingmc.tomly.nodes.impl.TableNode;
// Create a new table
Map<String, Node> dbConfig = new HashMap<>();
dbConfig.put("host", new StringNode("localhost", List.of(), null));
dbConfig.put("port", new NumberNode(5432L, List.of(), null));
dbConfig.put("username", new StringNode("admin", List.of(), null));
TableNode dbTable = new TableNode("database", dbConfig, List.of(), null);
doc.set("database", dbTable);Output:
[database]
host = "localhost"
port = 5432
username = "admin"// Create multiple server configs
List<Node> serverTables = new ArrayList<>();
for (int i = 1; i <= 3; i++) {
Map<String, Node> server = new HashMap<>();
server.put("name", new StringNode("web" + i, List.of(), null));
server.put("ip", new StringNode("192.168.1." + (10 + i), List.of(), null));
server.put("port", new NumberNode(8080L, List.of(), null));
serverTables.add(new TableNode(server, List.of(), null));
}
ArrayNode serversArray = new ArrayNode(serverTables, List.of(), null);
doc.set("servers", serversArray);Output:
[[servers]]
name = "web1"
ip = "192.168.1.11"
port = 8080
[[servers]]
name = "web2"
ip = "192.168.1.12"
port = 8080
[[servers]]
name = "web3"
ip = "192.168.1.13"
port = 8080Save to a file with default options:
WriterOptions options = WriterOptions.defaultOptions();
doc.save(Path.of("config.toml"), options);Preserve comments when saving:
WriterOptions options = WriterOptions.builder()
.writeHeaderComments(true)
.writeInlineComments(true)
.writeBlankLines(true)
.build();
doc.save(Path.of("config.toml"), options);Control line length and formatting:
WriterOptions options = WriterOptions.builder()
.maxLineLength(80)
.writeHeaderComments(true)
.build();
doc.save(Path.of("config.toml"), options);For more control, use TomlWriter class:
import com.github.groundbreakingmc.tomly.writer.TomlWriter;
Map<String, Node> nodes = doc.value();
WriterOptions options = WriterOptions.defaultOptions();
TomlWriter.write(nodes, Path.of("output.toml"), options);Map<String, Node> nodes = doc.value();
WriterOptions options = WriterOptions.defaultOptions();
String tomlString = TomlWriter.toString(nodes, options);
System.out.println(tomlString);import java.io.FileWriter;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
// To file with custom writer
try (FileWriter writer = new FileWriter("config.toml", StandardCharsets.UTF_8)) {
TomlWriter.write(doc.value(), writer, WriterOptions.defaultOptions());
}
// To string
StringWriter stringWriter = new StringWriter();
TomlWriter.write(doc.value(), stringWriter, WriterOptions.defaultOptions());
String result = stringWriter.toString();Load, modify, and save while preserving structure:
// Load with preservation
PreserveOptions parseOpts = PreserveOptions.builder()
.preserveHeaderComments(true)
.preserveInlineComments(true)
.preserveBlankLines(true)
.build();
TomlDocument doc = Tomly.parse(
Path.of("config.toml"),
false,
parseOpts
);
// Modify values
doc.set("version", new StringNode("2.0.0", List.of(), null));
doc.set("updated_at", new DatetimeNode(
OffsetDateTime.now(), 1, 0, List.of(), null
));
// Save with preservation
WriterOptions writeOpts = WriterOptions.builder()
.writeHeaderComments(true)
.writeInlineComments(true)
.writeBlankLines(true)
.build();
doc.save(Path.of("config.toml"), writeOpts);public void updateVersion(Path configPath, String newVersion) {
TomlDocument doc = Tomly.parse(
configPath,
false,
PreserveOptions.defaultOptions()
);
doc.set("version", new StringNode(newVersion, List.of(), null));
doc.save(configPath, WriterOptions.defaultOptions());
}public void addDatabaseConfig(Path configPath) {
TomlDocument doc = Tomly.parse(
configPath,
false,
PreserveOptions.defaultOptions()
);
// Create database section
Map<String, Node> dbConfig = new HashMap<>();
dbConfig.put("host", new StringNode("localhost", List.of(), null));
dbConfig.put("port", new NumberNode(5432L, List.of(), null));
dbConfig.put("username", new StringNode("admin", List.of(), null));
dbConfig.put("password", new StringNode("secret", List.of(), null));
TableNode dbTable = new TableNode(
dbConfig,
List.of(" Database configuration"),
null
);
doc.set("database", dbTable);
WriterOptions options = WriterOptions.builder()
.writeHeaderComments(true)
.build();
doc.save(configPath, options);
}public void updateMultipleValues(Path configPath, Map<String, String> updates) {
TomlDocument doc = Tomly.parse(
configPath,
false,
PreserveOptions.defaultOptions()
);
for (Map.Entry<String, String> entry : updates.entrySet()) {
doc.set(entry.getKey(), new StringNode(
entry.getValue(),
List.of(),
null
));
}
doc.save(configPath, WriterOptions.defaultOptions());
}
// Usage
Map<String, String> updates = Map.of(
"app.name", "NewAppName",
"app.version", "2.0.0",
"server.host", "192.168.1.100"
);
updateMultipleValues(Path.of("config.toml"), updates);public TomlDocument createConfigFromDefaults() {
Map<String, Node> root = new HashMap<>();
// App section
Map<String, Node> app = new HashMap<>();
app.put("name", new StringNode(
"MyApp",
List.of("# Application name"),
"required"
));
app.put("version", new StringNode(
"1.0.0",
List.of("# Semantic version"),
null
));
app.put("debug", new BooleanNode(
false,
List.of("# Enable debug mode"),
null
));
root.put("app", new TableNode(app, List.of(), null));
// Server section
Map<String, Node> server = new HashMap<>();
server.put("host", new StringNode("localhost", List.of(), null));
server.put("port", new NumberNode(8080L, List.of(), null));
root.put("server", new TableNode(
"server",
server,
List.of("# Server configuration"),
null
));
return new DocumentNode(new TableNode("", root, List.of(), null));
}
// Usage
TomlDocument template = createConfigFromDefaults();
WriterOptions options = WriterOptions.builder()
.writeHeaderComments(true)
.writeInlineComments(true)
.build();
template.save(Path.of("config.template.toml"), options);When doing round-trip serialization:
- All values and their types
- Table structure and nesting
- Array of tables
- Comments (if preservation enabled)
- Blank lines (if preservation enabled)
- Number formatting (hex/octal/binary converted to decimal)
- String quote style (normalized)
- Inline table formatting
Example:
port = 0x1F90
[database]
server = '192.168.1.1'
[database.credentials]
username = "admin"
password = "secret123"port = 8080
[database]
server = "192.168.1.1"
credentials = {username = "admin", password = "secret123"}Create entire documents without parsing:
public class ConfigBuilder {
public static TomlDocument buildConfig(
String appName,
String version,
String host,
int port
) {
Map<String, Node> root = new HashMap<>();
// Add simple values
root.put("name", new StringNode(appName, List.of(), null));
root.put("version", new StringNode(version, List.of(), null));
// Add server section
Map<String, Node> server = new HashMap<>();
server.put("host", new StringNode(host, List.of(), null));
server.put("port", new NumberNode((long) port, List.of(), null));
root.put("server", new TableNode(server, List.of(), null));
return new DocumentNode(new TableNode("", root, List.of(), null));
}
public static void main(String[] args) {
TomlDocument config = buildConfig("MyApp", "1.0.0", "localhost", 8080);
config.save(
Path.of("generated-config.toml"),
WriterOptions.defaultOptions()
);
}
}Handle errors during save operations:
import com.github.groundbreakingmc.tomly.exceptions.TomlSaveException;
try {
doc.save(Path.of("config.toml"), WriterOptions.defaultOptions());
} catch (TomlSaveException ex) {
System.err.println("Failed to save configuration: " + ex.getMessage());
ex.printStackTrace();
}Common causes:
- No write permission
- Disk full
- Invalid path
- I/O errors
- Use preservation judiciously: Only enable comment preservation if you need it
- Validate before saving: Ensure your modifications are valid
- Backup before modifying: Keep original files safe
- Use try-with-resources: For custom Writers
- Handle exceptions: Always catch TomlSaveException
- Test round-trips: Verify parse → modify → save cycles
- Document your changes: Add comments to explain modifications
- See Working With Comments for comment preservation