|
(I work at Notion) Our public API format is not the "native" format used by the Notion editor. The overly-nested format we designed the public API is aimed at supporting statically typed programming languages like Java or Golang that do not have (tagged) union types natively. Instead we represent each option in the union type as a nullable field pointing to a nested object. This makes the structure much easier to decode in these kinds of languages, but does make it more verbose. For a hypothetical typescript union type: | { type: 'plain', text: string, format: Formatting }
| { type: 'link', text: string, href: string, format: Formatting }
| { type: 'page-mention', page: { id: UUID, spaceId: UUID }, format: Formatting }
we end up producing a Java-style object like this: {
plain?: {
text: string,
format: Formatting
}
link?: {
text: string,
href: string,
format: Formatting
}
pageMention?: {
page: {
id: UUID,
spaceId: UUID
},
format: Formatting
}
}
You can see the native format by looking at API traffic in your browser devtools. Generally the native format is more confusing without type annotations. |
Rust's serde calls that "internally tagged": https://serde.rs/enum-representations.html