> For the complete documentation index, see [llms.txt](https://docs.internetobject.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.internetobject.org/schema-definition-language/data-types/string.md).

# String Types

The string type and its email and url shortcuts.

The **`string`** type validates text. It has two **predefined shortcuts** that are `string` with a built-in pattern: [Email](/schema-definition-language/data-types/string/email.md) and [URL](/schema-definition-language/data-types/string/url.md).

> `date`, `time`, and `datetime` are **not** string subtypes — they are their own types with their own values. See [Date and Time](/schema-definition-language/data-types/date-and-time.md).
>
> For how strings are *written* (open, quoted, raw), see [Strings](/structure-and-syntax/values/string.md).

## The string family

| Type     | Is                                          |
| -------- | ------------------------------------------- |
| `string` | any text                                    |
| `email`  | `string` validated against an email pattern |
| `url`    | `string` validated against a URL pattern    |

```ruby
contact: email, site: url
---
~ a@b.com, 'https://example.com'    # ✓
~ notanemail, 'https://example.com' # ✗ invalid-email
```

> **Quote values containing `:` or spaces** (URLs, times-of-day, "Last, First"). An unquoted `https://x.com` is misread because the open string ends at `:`.

## TypeDef

A `string` MemberDef accepts only the options below. Any other key is invalid.

| Option        | Type            | Description                                                                             |
| ------------- | --------------- | --------------------------------------------------------------------------------------- |
| `type`        | string          | `string`, `email`, or `url`. First positional value.                                    |
| `default`     | string          | Value used when the member is omitted. Second positional value.                         |
| `choices`     | array of string | Restricts the value to a fixed set. Third positional value.                             |
| `pattern`     | string          | A regular expression the value must match.                                              |
| `flags`       | string          | Regex flags for `pattern` (e.g. `i`).                                                   |
| `len`         | int ≥ 0         | Exact length, in **Unicode code points**.                                               |
| `minLen`      | int ≥ 0         | Minimum length, in **Unicode code points**.                                             |
| `maxLen`      | int ≥ 0         | Maximum length, in **Unicode code points**.                                             |
| `format`      | string          | *Presentation, write-only.* Form used when writing: `auto` (default), `regular`, `raw`. |
| `encloser`    | string          | *Presentation, write-only.* Quote character used when writing: `"` (default) or `'`.    |
| `escapeLines` | bool            | *Presentation, write-only.* Whether to escape line breaks when writing.                 |
| `optional`    | bool            | If `true`, the member may be omitted. Shorthand: `?` suffix.                            |
| `null`        | bool            | If `true`, the member may be `null`. Shorthand: `*` suffix.                             |

> **`len` precedence.** When `len` is set, `minLen` and `maxLen` are ignored.

> **Length is measured in Unicode code points** — **NOT** bytes, and **NOT** UTF-16 code units. `"café"` is 4 and `"🙂"` is **1**, even though the first is 5 bytes in UTF-8 and the second is 2 UTF-16 units.
>
> This has to be stated because every language's *default* string length means something different, and three of the common answers are wrong here:
>
> Code points are the only unit that is a property of the **text** rather than of an encoding or a runtime, and Internet Object is UTF-8 on the wire, where UTF-16 units have no meaning at all.
>
> The failure is invisible in ordinary testing: `"café"` measures 4 under all three interpretations, so a wrong implementation passes every ASCII and Latin-1 test and only diverges on characters outside the Basic Multilingual Plane. The conformance corpus probes it directly (`validation/strings-constraints.io`).

| Language   | Idiom                       | `"🙂"` |                |
| ---------- | --------------------------- | ------ | -------------- |
| Python     | `len(s)`                    | 1      | ✅              |
| Go         | `utf8.RuneCountInString(s)` | 1      | ✅              |
| Rust       | `s.chars().count()`         | 1      | ✅              |
| Go         | `len(s)`                    | 4      | ✗ bytes        |
| Rust       | `s.len()`                   | 4      | ✗ bytes        |
| JavaScript | `s.length`                  | 2      | ✗ UTF-16 units |

## Constraints

### minLen / maxLen / len

```ruby
name: { string, minLen: 5, maxLen: 20 }
---
~ Ethan              # ✓
~ Alexandra Daddario # ✓
~ Leo                # ✗ mismatched-min-len
```

### pattern

A regular expression. Use a [raw string](/structure-and-syntax/values/string/raw-strings.md) (`r'…'`) to avoid escaping backslashes.

```ruby
ssn: { string, pattern: r'^[0-9]{3}-[0-9]{2}-[0-9]{4}$' }
---
~ '123-45-6789'   # ✓
~ '12345678'      # ✗ mismatched-pattern
```

### choices

```ruby
dept: { string, choices: [cs, mech, civil] }
---
~ cs     # ✓
~ art    # ✗ mismatched-choice
```

> Quote choices that look like numbers or contain commas, e.g. `["19.02, 72.85"]`, so they are treated as strings.

## Optional, nullable & defaults

```ruby
nickname?*: { string, anonymous }   # optional + nullable, default "anonymous"
---
~ {}      # ✓ → "anonymous" (omitted, default applies)
~ N       # ✓ → null
~ John    # ✓ → "John"
```

| Input                       | Result                                                                                                                          |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| valid text                  | the string                                                                                                                      |
| fails a declared constraint | `mismatched-*` error, named after the keyword — `mismatched-min-len`, `mismatched-pattern`, `mismatched-choice`, …              |
| malformed for a sub-format  | `invalid-email` / `invalid-url` — `email` and `url` are types, so a non-conforming value is malformed rather than out of bounds |
| `N`, nullable (`*`)         | `null`                                                                                                                          |
| `N`, not nullable           | `forbidden-null` error                                                                                                          |
| omitted, `default` set      | the default                                                                                                                     |
| omitted, optional (`?`)     | absent                                                                                                                          |
| omitted, required           | `missing-value` error                                                                                                           |

## See Also

* [Strings (value syntax)](/structure-and-syntax/values/string.md)
* [Email](/schema-definition-language/data-types/string/email.md) · [URL](/schema-definition-language/data-types/string/url.md)
* [Date and Time](/schema-definition-language/data-types/date-and-time.md)
* [TypeDef](/schema-definition-language/advanced-schema-concepts/typedef.md) · [MemberDef](/schema-definition-language/advanced-schema-concepts/memberdef.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.internetobject.org/schema-definition-language/data-types/string.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
