Question
I want to write formatted output in Rust that looks like this:
write!(f, "{ hash:{}, subject: {} }", self.hash, self.subject)
However, curly braces have special meaning in Rust formatting macros, so the outer braces cannot be written directly like that.
I tried escaping them with backslashes:
write!(f, "\{ hash:{}, subject: {} \}", self.hash, self.subject)
That did not work either. Then I found documentation suggesting that literal {, }, or # characters may be escaped, and because \ is already an escape character in Rust strings, I also tried:
write!(f, "\\{ hash:{}, subject: {} \\}", self.hash, self.subject)
That still does not work. How do you correctly include literal curly braces in a Rust format string?
Short Answer
By the end of this page, you will understand how Rust format strings treat curly braces, how to print literal { and } characters, and why backslashes are not the correct solution. You will also see practical examples using write!, format!, and println!.
Concept
In Rust, formatting macros such as println!, format!, and write! use curly braces as placeholders.
For example:
println!("Hello, {}", name);
Here, {} tells Rust where to insert a value.
Because braces are part of the formatting syntax, Rust does not treat them like normal characters inside a format string. If you want to print a literal brace, you must escape it using doubled braces, not backslashes.
- Use
{{to print{ - Use
}}to print}
So this:
write!(f, "{{ hash:{}, subject: {} }}", self.hash, self.subject)
produces output like:
{ hash:123, subject: Rust }
Why this matters
Formatting is used everywhere in Rust:
Mental Model
Think of a Rust format string as a template with special slots.
{}means: “put a value here”{{means: “I really want an actual{character”}}means: “I really want an actual}character”
It is similar to quoting a special character in a mini-language. In Rust formatting, braces belong to the formatter itself, so you must tell Rust when a brace is part of the output instead of part of the formatting instruction.
Syntax and Examples
The key rule is simple:
"{{" // prints {
"}}" // prints }
Basic example
fn main() {
let hash = 42;
let subject = "Rust";
println!("{{ hash:{}, subject: {} }}", hash, subject);
}
Output:
{ hash:42, subject: Rust }
Using format!
fn main() {
let name = "Alice";
let message = format!("User record: {{ name: {} }}", name);
println!("{}", message);
}
Using write! in a Display implementation
Step by Step Execution
Consider this example:
fn main() {
let hash = 7;
let subject = "math";
let text = format!("{{ hash:{}, subject: {} }}", hash, subject);
println!("{}", text);
}
Step by step
-
Rust sees the format string:
"{{ hash:{}, subject: {} }}" -
The formatter reads
{{and turns it into a literal{. -
It then reads the first
{}and insertshash, which is7. -
It continues through the text
, subject:. -
It reads the second
{}and insertssubject, which is .
Real World Use Cases
Literal braces appear often in real Rust programs.
1. Custom Display output
When implementing Display for a struct, you may want object-like output:
write!(f, "{{ id:{}, name:{} }}", self.id, self.name)
2. Logging structured-looking messages
println!("event={{ type:{}, status:{} }}", event_type, status);
3. Generating JSON-like text for debugging
This is not real JSON serialization, but sometimes useful for quick debug output:
println!("{{ \"ok\": {}, \"count\": {} }}", ok, count);
4. Building configuration snippets
let line = format!("section {{ key = {} }}", value);
5. Template-style output
If your output language uses braces, such as config formats or DSLs, doubled braces are common in format strings.
Real Codebase Usage
In real projects, developers often combine escaped braces with common formatting patterns.
Guarded formatting
Only include a section when data exists:
if let Some(tag) = &self.tag {
write!(f, "{{ id:{}, tag:{} }}", self.id, tag)
} else {
write!(f, "{{ id:{} }}", self.id)
}
Error messages with structure
eprintln!("Parse error {{ line:{}, column:{} }}", line, column);
Debug-style manual formatting
Sometimes developers want a custom output format instead of using #[derive(Debug)].
write!(f, "User {{ id:{}, active:{} }}", self.id, self.active)
Prefer serializers when output must be strict
If you need actual JSON, developers usually use serde_json instead of manually formatting braces and quotes.
Common Mistakes
Here are the most common mistakes beginners make.
Mistake 1: Using single braces literally
Broken code:
println!("{ name: {} }", "Alice");
Why it fails:
- Rust thinks
{ name: {} }is formatting syntax, not plain text.
Fix:
println!("{{ name: {} }}", "Alice");
Mistake 2: Using backslashes to escape braces
Broken code:
println!("\{ name: {} \}", "Alice");
Why it fails:
- Backslashes escape characters in Rust strings, not formatting placeholders.
- The formatting system still sees
{and}as special.
Fix:
println!("{{ name: {} }}", "Alice");
Mistake 3: Forgetting that , , and all use the same rule
Comparisons
| Situation | Correct approach | Example |
|---|---|---|
| Print a value | Use {} | println!("{}", value); |
Print a literal { | Use {{ | println!("{{"); |
Print a literal } | Use }} | println!("}}"); |
| Escape a quote in a Rust string | Use \" | println!("\"hi\""); |
| Escape a newline in a Rust string | Use \n |
Cheat Sheet
// Literal braces in Rust format strings
"{{" // prints {
"}}" // prints }
// Normal placeholder
"{}" // inserts a value
Correct pattern
write!(f, "{{ hash:{}, subject: {} }}", self.hash, self.subject)
Rules
{}inserts a value{{prints{}}prints}- Backslashes do not escape formatting braces
- The same rule applies to:
println!print!format!write!writeln!
Quick examples
FAQ
How do I print a literal { in Rust?
Use {{ inside a format string.
How do I print a literal } in Rust?
Use }} inside a format string.
Why does \{ not work in println! or write!?
Because backslashes escape Rust string characters, not formatting placeholders. Format braces must be escaped with doubled braces.
Does this rule only apply to println!?
No. It also applies to format!, write!, writeln!, and related formatting macros.
What is the correct version of my original code?
write!(f, "{{ hash:{}, subject: {} }}", self.hash, self.subject)
Should I manually format JSON with braces like this?
Only for simple debug-like output. For real JSON, use a serializer such as serde_json.
Mini Project
Description
Create a small Rust program that prints user records in a custom structured format using formatting macros. This helps you practice inserting values with {} while printing literal braces with {{ and }}.
Goal
Build a program that formats and prints a few records like { id:1, name: Alice } correctly.
Requirements
- Define a struct to represent a user record.
- Create at least two example records.
- Print each record in a custom brace-based format.
- Use Rust formatting macros instead of manual string concatenation.
Keep learning
Related questions
Accessing Cargo Package Metadata in Rust
Learn how to read Cargo package metadata like version, name, and authors in Rust using compile-time environment macros.
Associated Types vs Generic Type Parameters in Rust: When to Use Each
Learn when to use associated types vs generic parameters in Rust traits, with clear rules, examples, and practical API design advice.
Can a Struct Extend Another Struct in Rust? Composition vs Inheritance
Learn how Rust handles struct reuse without inheritance, using composition, traits, and wrapper structs with practical examples.