.properties to TOML
Paste a .properties file and get real TOML back: dotted keys become nested tables, true and 8080 become a boolean and an integer instead of strings, and list.0 / list.1 collapse into an array.
What this tool does
It reads the .properties format properly — = or : or whitespace as the separator, # and ! comments, backslash line continuations, and \uXXXX escapes — then rebuilds the hierarchy the dotted keys imply and writes canonical TOML.
The intent it closes: "we are moving off .properties and I do not want to retype 200 keys." The properties format has no types and no structure; this restores both, so what comes out is a config a human can read and a TOML parser can validate.
Type inference is deliberate rather than aggressive: integers, floats, and the words true/false/yes/no are converted, and anything else stays a string. A number too large to represent exactly is kept as a string so no digits change.
When you'd reach for it
- Migrate a Spring Boot service.
application.propertiesbecomes a readable TOML config in one paste. - Read a config someone handed you. Nested tables make a 200-line properties file comprehensible.
- Compare two environments. Convert both and use the TOML Diff, which compares by value rather than by line.
- Move to a typed config loader. Rust, Python, and Go loaders all want types; properties has none.
- Recover arrays. Indexed keys from a generated file collapse back into TOML arrays.
How it works
Parse the format, rebuild the structure, type the values.
1. Parse the properties file
Lines are read one at a time. Blank lines and lines starting with # or ! are skipped. A trailing backslash joins the next line, with its leading whitespace stripped, exactly as Properties.load() does. The key ends at the first unescaped =, :, or run of whitespace; escapes in the key are unescaped. In the value, \n, \r, \t, and \uXXXX are decoded.
2. Rebuild the hierarchy
Each key is split on dots and the pieces become nested tables. Where a level is claimed both as a value and as a parent, the parent wins — a scalar cannot hold children. With Numeric keys set to rebuild, a table whose keys are exactly 0…n-1 becomes an array.
3. Type and emit
Each value is inspected and converted if it looks like a number or a boolean. Then the tree is written as canonical TOML with the sort order you chose. Keys that are not valid bare TOML keys are quoted automatically.
Options reference
Nesting
Split dots into tables is the point of the conversion: server.compression.enabled becomes enabled inside [server.compression]. Keep flat quoted keys leaves each key whole, quoted — useful when the dots are not really hierarchy (a key that is a hostname or a version).
Numeric keys
Generated properties files write lists as key.0, key.1. Rebuilding turns those into a TOML array. Keep them as tables when the numbers are identifiers rather than positions — a map keyed by tenant ID, say.
Types
Inference gives you port = 8080 instead of port = "8080". Turn it off for files where a digit string must stay a string — version numbers with leading zeros, account IDs, phone numbers.
Comma values
Spring writes list properties as a,b,c on one line. With splitting on, such a value becomes a TOML array; each element is type-inferred too. Leave it off if commas appear inside real values — a display name, an address.
Example
Input:
server.port=8080
server.compression.enabled=true
app.feature_flags.0=beta
app.feature_flags.1=metrics
Output:
[server]
port = 8080
[server.compression]
enabled = true
[app]
feature_flags = [ "beta", "metrics" ]
port is an integer and enabled a boolean thanks to inference; the two indexed keys became one array. Turn inference off and both would be quoted strings, which is what the properties file literally contained.
Limits and notes
- Comments are not carried over. They are skipped at parse time and there is no comment slot in the value tree.
- Real dots in keys get split. A key like
version.1.2becomes three levels. Switch nesting off for those files. - Sparse indexes stay tables.
list.0andlist.2with nolist.1cannot become an array without inventing an element. - Duplicate keys: last one wins. Same as
Properties.load(). If a file sets a key twice, only the final value survives.
FAQ
Does it handle line continuations?
Yes. A line ending in a single backslash continues onto the next, whose leading whitespace is stripped — the same rule Properties.load() uses for long values such as JDBC URLs.
What about \uXXXX escapes?
They are decoded to real characters, so an ASCII-escaped properties file comes out as readable UTF-8 TOML.
Will keys with dashes work?
Yes. spring.jpa.show-sql becomes show-sql inside [spring.jpa]. Dashes are legal in bare TOML keys, so no quoting is needed.
Why is one of my numbers still a string?
Either inference is off, or the number cannot be represented exactly as a 64-bit integer. In the second case keeping it as a string is deliberate — converting it would silently change the digits.
Is my file uploaded?
No. Everything runs in the browser, which matters because properties files routinely hold database URLs and passwords.