Zum Inhalt springen
Anjunar/ DOCS

JSON

Das Wire-Format zum Speichern von Dokumenten: ein versionierter Umschlag, ein Codec pro Knotentyp und volle Prüfung nicht vertrauenswürdiger Daten.

Umschlag

Knoten als Array

Knoten werden aufgelistet, nicht nach ID geschlüsselt. Ein Objekt würde doppelte IDs stillschweigend zusammenführen; als Array bleibt ein Duplikat sichtbar und wird zu DuplicateNodeId.

JSON, live

Bei jedem Commit aus dem Dokument kodiert.

A small document

A paragraph with strong and emphasized text, a link and inline code.

  1. First item

  2. Second item

20 Wörter · 21 Knoten
{ "format": "ember-document", "formatVersion": 1, "schemaVersion": 1, "root": "document", "nodes": [ { "id": "document", "type": "ember.core.root/1", "codecVersion": 1, "children": [ "json2", "json13", "json20" ] }, { "id": "json2", "type": "ember.rich-text.heading/1", "codecVersion": 1, "level": 2, "children": [ "json1" ] }, { "id": "json1", "type": "ember.core.text/1", "codecVersion": 1, "text": "A small document" }, { "id": "json13", "type": "ember.rich-text.paragraph/1", "codecVersion": 1, "children": [ "json3", "json4", "json5", "json6", "json7", "json9", "json10", "json11", "json12" ] }, { "id": "json3", "type": "ember.core.text/1", "codecVersion": 1, "text": "A paragraph with " }, { "id": "json4", "type": "ember.core.text/1", "codecVersion": 1, "text": "strong", "marks": [ { "mark": "ember.rich-text.strong/1" } ] }, { "id": "json5", "type": "ember.core.text/1", "codecVersion": 1, "text": " and " }, { "id": "json6", "type": "ember.core.text/1", "codecVersion": 1, "text": "emphasized", "marks": [ { "mark": "ember.rich-text.emphasis/1" } ] }, { "id": "json7", "type": "ember.core.text/1", "codecVersion": 1, "text": " text, a " }, { "id": "json9", "type": "ember.link.link/1", "codecVersion": 1, "href": "https://anjunar.com", "children": [ "json8" ] }, { "id": "json8", "type": "ember.core.text/1", "codecVersion": 1, "text": "link" }, { "id": "json10", "type": "ember.core.text/1", "codecVersion": 1, "text": " and " }, { "id": "json11", "type": "ember.core.text/1", "codecVersion": 1, "text": "inline code", "marks": [ { "mark": "ember.rich-text.inline-code/1" } ] }, { "id": "json12", "type": "ember.core.text/1", "codecVersion": 1, "text": "." }, { "id": "json20", "type": "ember.list.list/1", "codecVersion": 1, "kind": "ordered", "tight": true, "children": [ "json16", "json19" ] }, { "id": "json16", "type": "ember.list.item/1", "codecVersion": 1, "children": [ "json15" ] }, { "id": "json15", "type": "ember.rich-text.paragraph/1", "codecVersion": 1, "children": [ "json14" ] }, { "id": "json14", "type": "ember.core.text/1", "codecVersion": 1, "text": "First item" }, { "id": "json19", "type": "ember.list.item/1", "codecVersion": 1, "children": [ "json18" ] }, { "id": "json18", "type": "ember.rich-text.paragraph/1", "codecVersion": 1, "children": [ "json17" ] }, { "id": "json17", "type": "ember.core.text/1", "codecVersion": 1, "text": "Second item" } ] }
scala
val codecs = StandardJsonSupport.everything(media = MediaUrlPolicy.default) val json = DocumentJson.encodeToString(document, codecs) // Either[Vector[EncodeError], String] val decoded = DocumentJson.decodeString(json.toOption.get, schema, codecs) // Either[Vector[DecodeError], DecodeResult]
Versionen

Drei Nummern, drei Zuständigkeiten

Ein neuerer Payload wird sofort abgelehnt: Er kann Felder tragen, die dieser Build nicht versteht, und ihn als älteren zu lesen würde still Daten verlieren.

formatVersion
Form des Umschlags. Nie migriert; ein neueres Format braucht einen neueren Leser.
schemaVersion
Dokumentstruktur der Anwendung. Über SchemaMigrations angehoben.
codecVersion
Felder eines Knotentyps. Ein Codec darf ältere Versionen von sich lesen.
Ein Dokument, keine Sitzung

Der Payload hat keine Auswahl, keine Historie und keine Revision. Gespeichert wird das Dokument, nicht der Zustand einer laufenden Bearbeitung.