Question
Rust Raw String Literals: What r#"..."# Means and How Interpolation Works
Question
I saw the Rust syntax r#"..."#, but I could not find a clear explanation of what it does. It seemed useful for creating JSON.
let var1 = "test1";
let json = r#"{"type": "type1", "type2": var1}"#;
println!("{}", json); // => {"type": "type1", "type2": var1}
What is r#"..."# called in Rust, and what does it do? Also, how can I make var1 evaluate to its value inside the JSON string?
Short Answer
By the end of this page, you will understand Rust raw string literals, why they are useful for writing text like JSON without lots of escaping, and why variables such as var1 do not automatically evaluate inside them. You will also learn the usual Rust ways to insert values into strings, including format! and safer JSON-building approaches.
Concept
Rust's r#"..."# syntax is called a raw string literal.
A raw string literal tells Rust to treat most characters inside the string as plain text. This is especially useful when your string contains many double quotes, backslashes, or JSON-like content.
For example, a normal Rust string containing JSON often needs escaping:
let json = "{\"type\": \"type1\"}";
With a raw string literal, the same text is easier to read:
let json = r#"{"type": "type1"}"#;
Why it matters
In real code, raw strings are useful for:
- JSON snippets
- Regular expressions
- File paths
- SQL queries
- HTML templates
- Text that contains lots of quotes or backslashes
Important rule
A raw string literal does not perform variable interpolation.
That means this code:
let var1 = "test1";
let json = r#"{"type": "type1", "type2": var1}"#;
stores the exact text var1 inside the string. Rust does not replace it with the variable's value.
Mental Model
Think of a normal string as text inside a box where some characters have special meaning.
For example:
"means an escaped quote\nmeans a newline\\means a backslash
A raw string is like telling Rust:
"Do not interpret the contents. Just copy the text as written until you reach the matching closing marker."
So r#"..."# is like putting a note on the box saying literal text only.
But raw strings are still just strings. They are not templates. They do not scan for variable names and replace them.
So if you write:
r#"hello var1"#
Rust sees exactly the characters h e l l o space v a r 1.
Syntax and Examples
Basic syntax
let s1 = "normal string";
let s2 = r"raw string";
let s3 = r#"raw string with \"quotes\" inside"#;
let s4 = r##"raw string that can contain "# inside"##;
Normal string vs raw string
fn main() {
let normal = "{\"name\": \"Alice\"}";
let raw = r#"{"name": "Alice"}"#;
println!("{}", normal);
println!("{}", raw);
}
Both print the same output:
{"name": "Alice"}
The difference is readability in source code.
Inserting variables with format!
fn main() {
let = ;
= (, var1);
(, json);
}
Step by Step Execution
Consider this example:
fn main() {
let var1 = "test1";
let json = format!(r#"{{"type": "type1", "type2": "{}"}}"#, var1);
println!("{}", json);
}
Step by step
1. Create a variable
let var1 = "test1";
var1 points to the string slice "test1".
2. Call format!
let json = format!(r#"{{"type": "type1", "type2": "{}"}}"#, var1);
Rust processes the format string.
The raw string content is:
{{"type": "type1", "type2": "{}"}}
Because it is a raw string:
Real World Use Cases
When raw strings are useful
JSON samples
When you want to embed a fixed JSON example in code:
let sample = r#"{"status": "ok", "count": 3}"#;
Regular expressions
Regex patterns often contain many backslashes:
let pattern = r#"\d+\.\d+"#;
Windows file paths
let path = r#"C:\Users\Alice\Documents"#;
SQL queries
let query = r#"
SELECT id, name
FROM users
WHERE active = true
"#;
HTML or template text
let html = r#"<div class="card">Hello</div>"#;
When variable insertion is needed
In real applications, you often need dynamic values:
- building log messages
Real Codebase Usage
In real Rust projects, developers usually separate literal text from dynamic data.
Common patterns
1. Use raw strings for readable static text
let template = r#"{"type": "fixed"}"#;
Good when the content never changes.
2. Use format! for small dynamic strings
let user = "alice";
let msg = format!(r#"User "{}" logged in"#, user);
Good for simple string assembly.
3. Use serde_json for JSON payloads
use serde_json::json;
let payload = json!({
"user": "alice",
"active": true
});
This avoids broken JSON and handles escaping correctly.
4. Use guard clauses before formatting
(name: &) <> {
name.() {
;
}
((, name))
}
Common Mistakes
1. Expecting interpolation inside a string literal
Broken code:
let name = "Alice";
let s = r#"Hello, name"#;
This produces the literal text Hello, name.
Fix
Use format!:
let name = "Alice";
let s = format!("Hello, {}", name);
2. Confusing raw strings with formatted strings
Broken idea:
let value = 42;
let s = r#"Value: {}"#;
A raw string does not replace {} by itself.
Fix
Wrap it in format! or another formatting macro:
Comparisons
| Concept | What it does | Supports interpolation? | Best use |
|---|---|---|---|
Normal string literal "..." | Stores text, escape sequences are processed | No | General strings |
Raw string literal r#"..."# | Stores text literally with minimal escaping | No | JSON snippets, regex, HTML, SQL |
format!(...) | Builds a new string from a template and values | Yes | Dynamic strings |
println!(...) | Formats and prints output | Yes | Console output |
serde_json::json!(...) | Builds structured JSON values |
Cheat Sheet
Raw string literal syntax
r"text"
r#"text"#
r##"text"##
Rules
- Raw strings store text more literally than normal strings.
- Backslashes are not treated as escapes in the usual way.
- Quotes inside the string are easier to include.
- The string ends only at the matching closing delimiter.
- More
#characters let you include more complex content.
No interpolation
let name = "Alice";
let s = r#"Hello, name"#; // literal text
To insert values:
let s = format!("Hello, {}", name);
JSON with format!
let value = "test1";
let json = format!(r#"{{"type2": "{}"}}"#, value);
FAQ
What is r#"..."# called in Rust?
It is called a raw string literal.
Does a raw string evaluate variables automatically?
No. Rust string literals do not perform variable interpolation.
Why use # in a raw string?
The # helps Rust know where the raw string ends, especially when the content contains quotes.
What is the difference between r"..." and r#"..."#?
Both are raw strings. The # version is useful when the content includes double quotes or patterns that would otherwise end the string too early.
How do I insert a variable into a Rust string?
Use formatting macros such as format!, println!, or write!.
What is the best way to create JSON in Rust?
For real applications, use serde_json or serialize a struct with serde instead of building JSON manually.
Can I use raw strings with format!?
Yes. A raw string can be the format string passed to , but formatting still follows rules, including doubled braces for literal and .
Mini Project
Description
Build a small Rust program that creates a JSON message describing a user action. This project shows the difference between writing fixed JSON text, formatting a string with variable values, and building JSON safely with serde_json.
Goal
Create a program that outputs a JSON payload containing dynamic Rust variable values.
Requirements
- Create variables for a username and an action.
- Build one JSON string using
format!. - Build the same JSON payload using
serde_json::json!. - Print both results.
- Make sure the username and action appear as actual values, not as literal variable names.
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.