Properties to YAML Converter
Convert .properties to nested YAML or YAML back to .properties — dotted keys, indexed lists and \uXXXX escapes handled honestly — entirely on this device.
app.hosts[0] and app.hosts[1] become a YAML sequence, or stay as keys spelled with brackets. Infer writes true/false and plain numbers as YAML scalars; everything else stays quoted text. A .properties file is Latin-1, so non-ASCII text is written as \uXXXX — decode it, or pass it through unchanged.
Press ? for shortcuts
Do it offline:$ yq -p=props -o=yaml application.properties
How to use it
- Type, paste or drop a file up to 20 MB — the badge names the format found, and clicking it (or pressing s) converts the other way.
- Choose how indexed keys, value types and duplicates are handled going to YAML; choose the separator, comments and \uXXXX policy coming back.
- Read the panel under the output: it counts the comments removed, escapes decoded and values retyped.
- Copy the result, download it as .yml or .properties, or let Share pack the conversion into the link.
Paste a Spring .properties file to get nested YAML, or paste YAML to get .properties back — the badge names the detected direction and one click flips it. Dotted keys turn into nesting, app.hosts[0] turns into a sequence, and \uXXXX escapes decode. Whatever the target format cannot hold is counted under the output. Files up to 20 MB convert on this device.
How it works
Each line is read the way java.util.Properties reads it: the first unescaped =, : or run of spaces ends the key, a trailing backslash pulls in the next line without its indent, and #/! start a comment. Keys then split on unescaped dots, and [n] segments collect into sequences in index order.
Coming back, the tree is walked depth-first and every leaf is printed as text, because a .properties value has no type — 8080 and true are just characters until something reads them. Nulls and empty collections become an empty value; anything outside Latin-1 is written as \uXXXX.
Examples
# datasource
spring.datasource.url=jdbc:h2:mem:test
spring.datasource.username=sa
server.port=8080
spring:
datasource:
url: jdbc:h2:mem:test
username: sa
server:
port: 8080
The two dotted keys share the spring.datasource branch, and the = ends the key before any colon. The panel reports 1 comment line dropped — .properties comments are not carried into the converted output.
app.hosts[0]=a.example
app.hosts[1]=b.example
app.hosts[3]=d.example
app:
hosts:
- a.example
- b.example
- d.example
The Spring [n] convention becomes a real sequence. Index 2 is missing, so the run says: list `app.hosts` near line 1 uses indices 0, 1, 3 — the gaps were closed and the items written in index order.
greeting\ text = hello \
caf\u00e9
greeting text: hello café
An escaped space keeps the key in one piece, and the trailing backslash joins the next line without its four leading spaces. The \u00e9 decodes to é, counted.
server:
port: 8080
messages:
greeting: こんにちは
session:
timeout: null
server.port=8080
messages.greeting=\u3053\u3093\u306b\u3061\u306f
session.timeout=
Nesting flattens back to dotted keys. Five characters outside Latin-1 are re-escaped as native2ascii wrote them, and null becomes an empty value that any reader loads as "".
a=1
a.b=2
`a` is a value at line 1 and a parent key at line 2 — one YAML key cannot be both; rename one of them to convert.A file can carry both keys; YAML cannot carry both shapes at one position. Rather than pick a winner, the run stops and cites both lines.
Every example on this page is executed against the same engine that powers the tool, on every build.
Gotchas worth knowing
Three ways to write a separator, one meaning
a=1, b:2 and c.d 3 all set a key; surrounding spaces are trimmed. Lines starting with # or ! are comments, even indented. A key with no separator gets the empty string.
A continued line loses its indentation
A backslash at end of line joins the next one and strips that line's indent. Two backslashes are a literal backslash instead, and the line ends there.
Unknown escapes quietly lose the backslash
\t, \n, \r, \f and \\ mean what they look like; every other \x drops the backslash, so a\zb is the key azb. Each one is named with its line and column.
Repeat a key and the earlier line disappears
java.util.Properties keeps the last assignment, and so does this tool, naming the key and both lines. Set duplicate handling to Error and the run refuses instead.
The file is Latin-1, so \uXXXX is not decoration
java.util.Properties reads bytes as ISO-8859-1, which is why tooling writes caf\u00e9. Escapes decode on the way to YAML; on the way back every character above U+00FF is re-escaped.
What a round trip does not bring back
Comments and blank-line grouping are gone in the YAML direction, and the return trip prints every leaf as text. The counts list what to restore by hand.
Common errors
Malformed \uxxxx escape at line 1, column 12 — a \u escape needs exactly four hexadecimal digits; java.util.Properties refuses this file with the same message.- Three hex digits instead of four, usually a truncated paste or a hand-edited translation bundle. Java stops loading the whole file here too, so the fix is not optional.
`a` is a value at line 1 and a parent key at line 2 — one YAML key cannot be both; rename one of them to convert.- Real files grow into this: someone sets logging.level, then logging.level.root. Both work in .properties and neither can be dropped safely, so the run refuses with both lines cited.
Tabs are not allowed as indentation at line 2, column 1 — probable cause: YAML forbids tabs as indentation; replace the tab with spaces.- Coming back from YAML, the document has to parse before anything can be flattened. A tab-indenting editor trips this on the first nested line; reindent with spaces.
Input is larger than the 20 MB limit for this tool. For bigger files use the CLI: yq -p=props -o=yaml application.properties- The limit refuses, never truncates, and the same sentence appears in the page banner. Above 2 MB the tool waits for ⌘/Ctrl + Enter instead of converting on every keystroke.
FAQ
Does app.hosts[0] become a YAML list?
Yes — bracketed indices are collected into a sequence, which is what Spring Boot binds a list from. Gaps are filled in index order with a note naming the indices seen. A plain digit segment like a.0.b is not one.
Why is server.port a number in YAML but text coming back?
Going out, plain integers, decimals and true/false are written as typed scalars, matching Spring's own YAML, and the count says how many changed. Coming back there is nothing to write but characters. Switch value types to Always text for a strict trip.
Are my \uXXXX escapes and passwords sent anywhere?
No. The conversion runs in this browser tab, and nothing is uploaded. When the input looks credential-shaped — a spring.datasource.password line — the tool also skips saving it for next time.
Keyboard shortcuts
- ⌘/Ctrl + Enter
- Run the conversion; required above 2 MB.
- ⌘/Ctrl + S
- Save output as .yml or .properties.
- ⌘/Ctrl + C
- Copy the whole result when nothing is selected.
- ⌘/Ctrl + Shift + C
- Copy the whole result despite a selection.
- s
- Convert the other way; undo restores.
- t
- Next color theme.
- ? or ⌘/Ctrl + /
- Show this shortcut list.
- Esc
- Close the top overlay; panes stay put.