5. Strings
Readable Object Notation
Strings contain Unicode text encoded as UTF-8. They can contain spaces, line breaks, and embedded null characters, but are not containers for arbitrary invalid UTF-8 bytes. RON has several string spellings, all of which produce the same kind of value.
Table of Contents
5.1. Bare strings ↑
In compact notation, an unquoted word is read as a single token: a sequence of source characters recognized as one unit.
A bare token is nonempty and ends at whitespace, a comma, or one of the container delimiters [, ], {, and }.
Characters U+0000 through U+001F cannot occur within a bare token.
A double quote at the start opens a quoted or fenced string.
A leading # introduces a tagged element; quote a string that begins with #.
A leading < introduces a tag-only map; quote a string that begins with <.
Double quotes may occur after the first character of a bare token.
Apostrophes are ordinary text, including at the start of a token.
Other punctuation is ordinary text, except for a comment marker where comments are allowed.
In value position, a token matching a number, null, true, or false denotes that value.
Other bare tokens denote strings.
[hello .-#1 user/name a:b + don't 🙂 "42" "null"]
[hello .-#1 user/name a:b + don't 🙂 "42" "null"]
[ "hello", ".-#1", "user/name", "a:b", "+", "don't", "🙂", "42", "null" ]
Parentheses and ^ are ordinary characters in bare strings, including at the beginning:
caret ^name label hello (world) items [foo(bar) (bar) abc) ^name]
caret ^name items [foo(bar) (bar) abc) ^name] label hello (world)
{
"caret": "^name",
"label": "hello (world)",
"items": [
"foo(bar)",
"(bar)",
"abc)",
"^name"
]
}
In a line-oriented map, a bare value extends from the end of the key to the end of the line, an enclosing closing delimiter, or a trailing comment. It can contain spaces and commas. Leading and trailing spacing and a final comma are not part of the string.
title A small book about RON summary Plain text, with punctuation,
summary Plain text, with punctuation title A small book about RON
{
"title": "A small book about RON",
"summary": "Plain text, with punctuation"
}
The value of title is A small book about RON.
The value of summary is Plain text, with punctuation.
The comma between words belongs to the string, while the final comma does not.
5.2. Double-quoted strings ↑
Double-quoted strings begin and end with ".
They use JSON string syntax, including the following escapes:
| Escape | Character |
|---|---|
\" |
Double quote |
\\ |
Backslash |
\/ |
Forward slash |
\b |
Backspace |
\f |
Form feed |
\n |
Newline |
\r |
Carriage return |
\t |
Tab |
\uHHHH |
A Unicode escape with four hex digits |
A double quote or backslash within the contents must be escaped.
Control characters U+0000 through U+001F must also be escaped, so a literal line break cannot occur inside a double-quoted string.
An embedded null character is written \u0000.
Unicode characters outside the Basic Multilingual Plane can be written directly as UTF-8 or as a pair of UTF-16 surrogate escapes.
An unpaired surrogate is invalid.
["" "hello world" "say \"hello\"" "first\nsecond" "\u03b5" "🙂"]
[ "" hello world say "hello" """ first second """ ε 🙂]
[ "", "hello world", "say \"hello\"", "first\nsecond", "ε", "🙂" ]
5.3. Fenced strings ↑
Two or more double quotes enclose a fenced string. Quotes inside the string are literal when their run is shorter than the fence. Backslash escapes work as in ordinary quoted strings; fences remove the need to escape quotes.
""say "hello", then leave""
""say "hello", then leave"""say \"hello\", then leave"
The opening run determines the fence length. If the content contains three consecutive quotes, use four quotes for the fence:
""""contains """ inside""""
""""contains """ inside"""""contains \"\"\" inside"
With a two-quote fence, content must start immediately after the opening quotes.
Two quotes followed by whitespace, a closing delimiter, a comma, or the end of
input mean the empty string "". Use a longer fence when the content begins
with one of those characters.
Literal backslashes are written as \\ in both ordinary and fenced strings:
"""C:\\my files\\notes.txt"""
"C:\\my files\\notes.txt"
"C:\\my files\\notes.txt"
5.4. Single-line and multiline fences ↑
A fence of three or more quotes followed only by spaces or tabs and a newline selects multiline mode. Two quotes alone still mean the empty string. For three or more quotes, the newline selects the mode: the same fence can be used on one line or across several lines.
This single-line input contains hello world with no final newline. Its
canonical spelling is an ordinary quoted string because it needs no escapes:
Putting the same text on its own line produces the same string. The newline
after the opening fence and the newline before the closing fence are delimiters,
not content. This also formats to "hello world":
Multiline fence lines are not part of the string. The closing fence uses the same number of quotes on a separate line. Common indentation is removed from nonblank content lines. Additional indentation and internal newlines are retained. One boundary newline is removed before the closing fence; an extra blank line preserves an intentional trailing newline. Whitespace may surround the closing fence, and a trailing comma or a permitted comment may follow it.
message """ first line indented line last line """
message """ first line indented line last line """
{
"message": "first line\n indented line\nlast line"
}
A longer fence also lets a multiline string contain a shorter fence as text:
""""
A literal fence:
"""
""""
""""
A literal fence:
"""
"""""A literal fence:\n\"\"\""
An empty string is "". An empty multiline block also produces an empty string.
Apostrophes never open strings or fences; they are ordinary characters:
['plain' don't 'true']
['plain' don't 'true']
[ "'plain'", "don't", "'true'" ]
5.5. Canonical string formatting ↑
The formatter chooses a spelling from the decoded string value, not from the escapes or quotes used in the input. It removes quotes when the value can be written bare in that position, including spaces in a line-oriented map value:
Unicode escapes become literal characters. Printable characters such as ε and 🙂 can be bare strings:
A root string containing spaces still needs quoting. When a quoted value has no escapes to avoid, the formatter uses ordinary double quotes. When it contains double quotes, the formatter uses a fence instead of escaping them. The shortest unambiguous fence has two quotes:
"say \"hello\", then leave"
""say "hello", then leave"""say \"hello\", then leave"
The canonical fence is longer than every double-quote run in the contents. Three embedded quotes therefore produce a four-quote fence:
"contains \"\"\" inside"
""""contains """ inside"""""contains \"\"\" inside"
Quotes remain necessary when removing them would change the value's type. The following stays a string rather than becoming a boolean:
Escaped quotes are accepted in input, but canonical RON uses \" only for a leading quote in a one-line key.
A quote at the end of a fenced value stays literal:
Control characters retain their escapes, including inside fences. Backslashes
remain escaped too. A value beginning with a quote uses a multiline fence to
keep that quote separate from the opening delimiter. For an object key, which
must stay on one line, a leading quote uses \".
Tabs, null characters, and other control characters retain their escapes:
A string containing line breaks uses a multiline fence when indentation can be preserved. A trailing newline in the value requires an extra blank line before the closing fence:
Without a trailing newline in the value, the closing fence immediately follows the last content line. It does not add a newline to the value: