JSON-Schema. Sein oder Nichtsein?

Architektur: die Kunst, unnötig notwendig zu machen.

Frederick Kiesler

Es ist für niemanden ein Geheimnis, dass für jeden Webdienst, der das SOAP-Protokoll im XML-Format verwendet, eine zuverlässige und bewährte Lösung die vorläufige Entwicklung des XML -Schemas (xsd-Schema) ist, das die Datentypen und die Struktur von XML-Nachrichten beschreibt. Mit diesem Ansatz haben Entwickler einen klaren Vorteil: Sie haben streng standardisierte Regeln für die Struktur von Nachrichten, die im Schema festgelegt sind, die Anzahl der Regeln ist begrenzt und Sie können die Überprüfung neuer Nachrichten im XML-Format automatisieren.

Es ist jedoch auch bekannt, dass die XML-Sprache aufgrund ihrer höheren Schwere (XML-Schwere) sowie der Verbreitung des Architekturstils der REST-Softwareentwicklung (REpresentational State Transfer) für verteilte Systeme durch die JSON-Markup-Sprache (JavaScript Object Notation) ersetzt wurde. Obwohl der REST-Stil selbst nicht die Verwendung von JSON erfordert (man kann sagen, dass er überhaupt nichts erfordert, sondern „empfiehlt“), wird JSON, wie die Praxis zeigt, häufiger bei der Entwicklung einer REST-API verwendet, um den Nachrichtentext zu beschreiben.

Die Praxis der Entwicklung einer REST-API mit JSON-Nachrichten hat sich also fest in das Leben der IT in Russland (und nicht nur in unserem) eingefügt, obwohl die Erfahrung mit der Beschreibung der Nachrichtenstruktur in Form eines XML-Schemas das Leben von Webdienstentwicklern auf einmal erheblich vereinfacht hat. wird bei JSON-Nachrichten dauerhaft ignoriert. Aber nicht jeder, der sich nur freuen kann.

Als Entwickler, die mit XML Schema vertraut sind, das Rad jedes Mal beim Parsen von Dokumenten neu erfinden und die Validierungslogik neu erfinden mussten, wurde ein ähnlicher Entwurf für ein JSON-Schema erstellt . Es ist unter json-schema.org verfügbarsowie eine Reihe von Dokumenten zur Änderungsgeschichte und Anwendungsbeispiele. Und trotz der Tatsache, dass es im Entwurfsstatus veröffentlicht wird, wird es seit langem von allen gängigen Entwicklungsplattformen und Bibliotheken in verschiedenen Sprachen unterstützt. Das JSON-Schema

selbst bietet weniger Funktionen zur Nachrichtenstrukturierung als das XML-Schema . Was durch das XML-Schema leicht beschrieben werden kann, ist nicht immer eine triviale Aufgabe, die nach Möglichkeit mit dem JSON-Schema wiederholt werden muss. Aber hier würde ich diese Tatsache als Vorteil betrachten. Warum? Es ist bekannt, dass je einfacher und linearer der Algorithmus des Systems ist, desto zuverlässiger ist er, desto einfacher ist die Struktur des Dokuments, desto einfacher ist es für die Wahrnehmung usw. Ich kann nicht anders als zu zitieren:



"Alles Geniale ist einfach und alles Einfache ist genial . " Und wenn es nicht möglich ist, die komplexe Struktur des Dokuments und die Menge akzeptabler Optionen mithilfe des Schemas zu beschreiben, lohnt es sich vielleicht, in Richtung einer Vereinfachung der Struktur und Logik der Erstellung dieses Dokuments zu schauen?

Vorwort


Worum geht es in diesem Artikel?

Ich möchte mehr Aufmerksamkeit auf die Vorteile der Beschreibung von JSON-Nachrichten lenken, die vom JSON-Schema übertragen werden. Trotz der Tatsache, dass die Entwicklung einer REST-API ohne JSON-Schema „am Eingang“ immer einfacher und schneller ist, führt das Fehlen des Systems auf die eine oder andere Weise zu einem Anstieg der Kosten für Systemwartung und -support. Außerdem trägt jede vorläufige Untersuchung der Nachrichtenstruktur zu einer besseren Organisation des Nachrichtenaustauschs bei, ohne dass unnötige Doppelarbeit beim Datenaustausch und allgemeine Regeln für deren Verarbeitung erforderlich sind.

Um Informationen in der russischsprachigen Gemeinschaft über die Möglichkeiten des JSON-Schemas und die Regeln für die Arbeit damit zu verbreiten, werde ich meine Erfahrungen mit spezifischen Beispielen im Rahmen dieses Artikels teilen.

Formulierung des Problems


Bevor ich mit dem Studium von JSON und JSON Schema beginne, werde ich die Aufgabe beschreiben, für die wir alle folgenden Beispiele betrachten werden.

Betrachten Sie ein Rollenverwaltungsmodell in einer Organisation. Wir gehen davon aus, dass wir Referenzinformationen zum vorhandenen Vorbild in Nachrichten im JSON-Format an abhängige Systeme übertragen müssen, indem wir einen REST-Service aufrufen.

Beschreibung der Aufgabe:

Die Organisation hat Mitarbeiter, die häufig gleichzeitig in mehreren Systemen arbeiten müssen. Darüber hinaus kann die Zugriffsebene (Berechtigung) auf verschiedene Komponenten des Systems (Ressourcen) für verschiedene Mitarbeiter je nach ihrer Rolle in der Organisation unterschiedlich sein und sollte während der Benutzerautorisierung im System gesteuert werden.

Beispielsweise hat ein Buchhalter (Rolle) Lese- und Bearbeitungszugriff (Vorgänge / Anmeldeinformationen) auf Gehaltsabrechnungen (Ressourcen) für die Löhne aller Mitarbeiter, und ein Analyst (Rolle) hat beispielsweise nur Lesezugriff (Vorgang / Anmeldeinformationen) entsprechend seiner Gehaltsabrechnung (Ressource).

Es ist notwendig, ein Rollenmanagementmodell in einer Organisation zu entwerfen und zu beschreiben. Verfügbare Rollen, eine Reihe möglicher Befugnisse und Ressourcen im System müssen auf Anfrage auf andere Systeme übertragen werden.


Abbildung 1. Darstellung der Komponenten des Vorbilds Die

Methoden zur Beschreibung und Implementierung des Vorbilds können unterschiedlich sein. In diesem Fall können wir jedoch unabhängig von der Implementierung, meistens im Vorbild, die folgenden Grundkomponenten unterscheiden:

  1. Rolle (z. B. Manager, Buchhalter usw.).
  2. Ressource (z. B. Dokument, Eigentum usw.).
  3. Operation / Autorität (z. B. Lesen, Drucken, Erstellen usw.).

Bei der Beschreibung des rollenbasierten Zugriffs (als eine der möglichen Optionen) wird eine diskrete Zugriffsmatrix basierend auf ausgewählten Entitäten erstellt, z. B.:

Tabelle 1. Diskrete Zugriffsmatrix.
Ressource: DokumenteRessource: Objekte
Rolle: Managerlesen, druckenlesen, erstellen
Rolle: Buchhalterlesen, erstellenlesen

Im weiteren Verlauf des Artikels werden wir uns zunächst mit der theoretischen Komponente des Textformats für den Austausch von JSON-Daten und den Regeln für deren Strukturierung mithilfe des JSON-Schemas vertraut machen. Als Beispiele werde ich die Entitätsentitäten für die Rollen, Ressourcen und Operationen in der JSON-Sprache und ihre JSON-Schemata in unserem beschreiben Aufgabe setzen.

JavaScript-Objektnotation (JSON)


JSON (English JavaScript Object Notation) ist ein textbasiertes Datenaustauschformat, das auf JavaScript basiert.

Theorie


Die JSON-Auszeichnungssprache definiert einen begrenzten Satz von Datentypen. Verwenden Sie für das Paar {"Schlüssel": Wert} für den "Schlüssel" immer die Typzeichenfolge, für den "Wert" gelten die Typen: Zeichenfolge, Zahl, Objekt (Typ JSON), Array, Boolescher Wert (wahr oder falsch) und Null.


Abbildung 2. JSON-Datentypen

Die Abbildung zeigt die grundlegenden Typen und Beispiele für ihre Verwendung. Meiner Meinung nach einfach genug.

Die JSON-Syntax ist eine Teilmenge der JavaScript-Syntax, wobei:

  1. Daten werden paarweise geschrieben {"Schlüssel": Wert}.
  2. Daten werden durch Kommas getrennt.
  3. In geschweiften Klammern werden Objekte aufgezeichnet.
  4. Arrays werden in eckigen Klammern angegeben.
  5. Bei den Namen der "Schlüssel" wird zwischen Groß- und Kleinschreibung unterschieden.


Abbildung 3. JSON-Syntax

Trainieren


Stellen Sie sich ein Beispiel für ein Rollenverzeichnis vor, das wir im Service übertragen werden:


Abbildung 4. Beschreibung eines Rollenverzeichnisses im JSON-Format

Aus dem Beispiel geht hervor, dass wir trotz einer so geringen Anzahl von Basistypen in Kombination bei Bedarf komplexere Nachrichtenstrukturen erstellen können. Hier beschreibe ich insbesondere das Rollenverzeichnis durch ein Objekt von Arrays, die andere Objekte enthalten (in Abbildung 4 sind zwei Rechtecke hervorgehoben).

In tabellarischer Form kann das Verzeichnis mit den Tools von json-visualization wie folgt dargestellt werden:


Abbildung 5. Visualisierung des Rollenverzeichnisses im JSON-Format

Das Verzeichnis enthält relativ gesehen drei „Tabellen“ zum Zuweisen von Rollen in einer Gruppe von Administratoren, Buchhaltern und Mitarbeitern. Die Zusammensetzung der „Attribute“ kann bei Bedarf erweitert werden.

Die visuelle Darstellung vereinfacht meiner Meinung nach die Wahrnehmung der Textbeschreibung. Wir werden eine ähnliche Struktur für die beiden anderen Verzeichnisse festlegen. Ich werde im Folgenden nur ein Beispiel für eine Tabellenansicht für ein Verzeichnis von Berechtigungen (Operationen) und Ressourcen geben.


Abbildung 6. Visualisierungen des Berechtigungsverzeichnisses im JSON-Format


Abbildung 7. Visualisierungen des Ressourcenverzeichnisses im JSON-Format

Quellnachrichten im JSON-Textformat für das Verzeichnis der Rollen , Ressourcen und Berechtigungen können über den Link heruntergeladen / angezeigt werden .
Kommen wir nun zum interessantesten: JSON-Schema studieren und ein Schema für unsere Nachschlagewerke erstellen!

JSON-Schema


Theorie


Da das JSON-Schema im JSON-Format geschrieben ist, unterstützt es alle JSON-Typen sowie den Zusatz: den Integer-Typ, der ein Subtyp des Zahlentyps ist. Das Schema selbst ist ein JSON-Objekt und soll Daten im JSON-Format beschreiben. Das Folgende ist ein Schema der Datentypen, die zum Erstellen des Schemas selbst verwendet werden:


Abbildung 8. Datentypen des JSON- Schemas

Wie Sie in der Abbildung sehen können, verwendet das Schema dieselben Datentypen sowie dieselben Syntaxprinzipien wie für ein reguläres JSON-Dokument (siehe Abbildung) Abbildung 3.

Nun betrachten wir das Wichtigste - die Regeln, die im Schema zum Festlegen von Einschränkungen und zum Strukturieren von JSON-Nachrichten verwendet werden.

Mit dem JSON-Schema können Sie:

  1. JSON.
  2. , — «keywords», .

Einige "Schlüsselwörter" sind rein beschreibend, wie z. B. "Titel", "Beschreibung" usw., die lediglich den Zweck des Schemas beschreiben. Andere werden verwendet, um das Dokument zu identifizieren: "$ schema". Dieses Schlüsselwort wird verwendet, um die gewünschte Version des Schemas anzugeben. Der Wert dieses Schlüsselworts sollte eine Zeichenfolge sein, die einen URI darstellt, z. B. "$ schema": " json-schema.org/draft-04/schema# ".

Es ist sehr wichtig zu beachten, dass nicht alle Versionen von Ihrem Schaltungswerkzeug unterstützt werden können. Aber der 4. Entwurf wird von fast allen unterstützt. Die neuesten Änderungen (JSON Schema 2019-09 Release Notes) für verschiedene Versionen finden Sie unter json-schema.org/draft/2019-09/release-notes.html .

Die verbleibenden Schlüsselwörter werden direkt zur Validierung des JSON-Dokuments verwendet. Wir werden sie jetzt betrachten.

Tabelle 2. Analyse der JSON-Schemastruktur. Schlüsselwörter und ihre Anwendungsbeispiele.
Eine ArtSchlüsselwörter)Beispiel / Beschreibung
"Schlüsselwörter" zur Beschreibung des Schemas"$schema"
"$schema": http://json-schema.org/draft-04/schema#

Wird verwendet, um die Entwurfsversion des Schemas festzulegen.
"$id"
"$id": "http://archi-blair.com/schemas/RolesDictionaryDef.json#"

Wird verwendet, um eine eindeutige Kennung für ein Dokument oder seine Unterschaltungen anzugeben.
"title"
"description"
"examples"
"comment"

{
"title": "JSON schema for dictionary",
"description": " ",
"examples": ["user", "manager"],
"comment": "     ))"
}

Allgemeine "Validierungsschlüsselwörter" unabhängig vom Artikeldatentyp"enum"
{"enum": [ "administrator", "superuser" ]}

Es wird geprüft, ob mindestens 1 Wert übereinstimmt.
"const"
{"const": "user" }

Es wird geprüft, ob der eingestellte Wert genau eingehalten wird.
"type"
{"type": ["number", "string", "null", "boolean"]}
{"type": "array"}

Gibt den Datentyp an, den das Schema verwenden wird. Dieses Schlüsselwort ist optional, und der Schlüsselwortwert kann eine Zeichenfolge sein, die einen gültigen Datentyp darstellt, oder ein Array von Zeichenfolgen, die gültige Datentypen darstellen.
Keywords, ,"type": "string"

minLength
maxLength
pattern
contentEncoding
contentMediaType

{
"type": "string",
"minLength": 3,
"maxLength": 10,
"pattern": "^test\\/[a-z-]+$",
"contentEncoding": "base64",
"contentMediaType": "application/json"
}

.
"type": "number" "type": "integer"

minimum
exclusiveMinimum
maximum
exclusiveMaximum
multipleOf

{
  "type": "number",
  "minimum": 1.5,
   "exclusiveMinimum": true,
   "maximum": 12.3,
   "exclusiveMaximum": true,
   "multipleOf": 0.5
}

.
"type": "object"

properties
required
dependencies
minProperties
maxProperties
propertyNames
patternProperties
additionalProperties


"employees": {
 "description": "",
 "type": "array",
  "uniqueItems": true,
   "items": {
     "type": "object",
     "properties": {
           "name": {
               "type": "string",
               "enum": ["employee"],
               "enumNames": [""]
	    },
            "enabled": {
                "type": "boolean",
                "default": true
             }
    },
 "additionalProperties": false
 }
}

, ( ).
"type": "array"

minItems
maxItems
uniqueItems
contains
items
additionalItems


"employees": {
 "description": "",
 "type": "array",
 "uniqueItems": true,
 "items": {
    "type": "object",
    "properties": {
          "name": {
               "type": "string",
               "enum": ["employee"],
               "enumNames": [""]
            },
          "enabled": {
                "type": "boolean",
                "default": true
            }
     },
 "additionalProperties": false
 }
}

, ( ).
"type": "boolean"

{"type": "boolean"}

boolean (true false).
"type": "null"

{"type": "null"}

null «» .
"type": "____"
"format": "____"

{
  "type": "string",
  "format": "date"
}

format . , .. -, , , .
"type": "____"
"default": "____"

{
"enabled": {
	"type": "boolean",
	"default": true
}	

.

, .
"not"
"if-then-else"

{
  "not": {
    "type": "string"
  }
}

, .
,"anyOf"
"oneOf"
"allOf"

{
  "type": "string",
  "anyOf": [
    {"const": "user"},
    {"const": "manager" }
  ]
}

, .
,"$id" "$ref"RolesDictionaryDef.json:

{
"$id": http://archi-blair.com/schemas/RolesDictionaryDef.json#
}

1 $ref ( ):


"items": {
"type": "object",
"minLength": 1,
"properties": {
  "name": {
  "description": "  ",
  "type": "string"
   },
"description": {
  "description": " ",
  "type": "string"
 },
"dictionaryGroup": {
  "$ref": "RolesDictionaryDef.json#/definitions/roles"
    }
},
"additionalProperties": false
}

2 JSON. , $ref .
"$ref" "definitions""$ref": "#/definitions/roles" , «definitions»:

{
"$schema": "http://json-schema.org/draft-04/schema#",
"description": " ",
"type": "object",
"properties": {
"dictionaries": {
   "description": "",
   "type": "array",
   "maxItems": 1,
   "items": {
      "type": "object",
      "minLength": 1,
      "properties": {
               "name": {
                  "description": " ",
                  "type": "string",
                  "enum": [
                     "Roles Dictionary"
                     ]
                 }
       "dictionaryGroups": {
             "$ref": "#/definitions/roles",
             "description": " "
          }
      },
 "additionalProperties": false
   }
  }
 },
 "additionalProperties": false,
     "definitions": {
          "roles": {
             "description": "",
             "type": "object",
             "properties": {
             "administrators": {
             "description": "",
             "type": "array",
             "uniqueItems": true,
             "items": {
             "type": "object",
             "properties": {
                   "name": {
                      "type": "string",
                      "enum": [
                         "administrator", 
                         "superuser"
                          ],
                        "enumNames": [
                          "", 
                          "-   "
                           ]
                         },
                    "enabled": {
                    "type": "boolean",
                    "default": true
                  }
              },
    "additionalProperties": false
      }
    }			
   },
  "additionalProperties": false
  }
 },
 "$id": "http://archi-blair.com/schemas/RolesDictionaryDef.json#"
}

, . $ref definitions.
"$ref"
.
"$ref": " #/definitions/roles"
"$ref": "RolesDictionaryDef.json#/definitions/roles"

, .
, .

Wir haben uns die Schlüsselwörter für das JSON-Schema angesehen, um die zukünftige Struktur unserer Nachrichten im JSON-Format zu beschreiben.

Hier finden Sie weitere Beispiele für die Verwendung von Schlüsselwörtern.

Trainieren


Wenn wir Beispiele für abgeschlossene JSON-Schemata betrachten, werden wir ähnlich wie bei Beispielen für die Arbeit mit Nachrichten selbst im JSON-Format vorgehen. Jene. Wir werden die visuelle Darstellung in Baum- und Tabellenform für unsere Verzeichnisse von Verzeichnissen mit Rollen, Ressourcen und Befugnissen (Operationen) verwenden. Mit dem Text der Schemata schlage ich vor, dass interessierte Leser sich selbst mit git vertraut machen .

Das folgende Diagramm zeigt eine Rollenreferenz.


Abbildung 9. Beispiel für ein JSON-Schema für das Rollenverzeichnis

Wie in der Abbildung dargestellt, ist das Schema ein JSON-Objekt und beschreibt unsere Nachricht zum Übertragen des Rollenverzeichnisses in JSON, die in Abbildung 4 dargestellt ist. Im aktuellen Beispiel kann gezeigt werden, wie das JSON-Schema verwendet wird Ein aus Objekten bestehendes Array-Objekt wird beschrieben.

Die Schemata der beiden anderen Verzeichnisse (Berechtigung und Ressourcen) sind in ihrer Struktur identisch mit dem Schema für das Rollenverzeichnis, daher werde ich sie hier nicht angeben, aber ich werde ein Schema angeben, das alle drei Verzeichnisse kombiniert.

Leider passt das Schema des gesamten Verzeichnisses während der Erweiterung nicht auf den Bildschirm, daher werden wir einen Teil davon betrachten.


Abbildung 10. Ein Beispiel für ein JSON-Schema-Verzeichnis, das ein Verzeichnis mit Rollen, Berechtigungen und Ressourcen kombiniert.

In der Abbildung sehen wir, dass einige der Objekte im Array von Verzeichnissen mit dem Schlüsselwort "anyOf" verbunden sind.

Vielleicht ist auch eine tabellarische Darstellung des Verzeichnisses visueller.

Betrachten Sie ein weiteres wichtiges Merkmal unseres Schemas:


Abbildung 11. Ein Beispiel für ein JSON-Schema eines Verzeichnisses, das ein Verzeichnis mit Rollen, Berechtigungen und Ressourcen in einer Tabellenansicht

kombiniert. Aus der Abbildung geht hervor, dass ein Kombinationsverzeichnis keinen Code aus zuvor entwickelten Verzeichnissen mit Rollen, Berechtigungen und Ressourcen dupliziert, sondern das Schlüsselwort "$ ref" verwendet ""

Die in den Beispielen berücksichtigten Verzeichnisse befinden sich im selben Verzeichnis. Falls erforderlich, kann diese Regel jedoch nicht beachtet werden, sondern kann in verschiedenen Verzeichnissen abgelegt werden, wobei beim Herstellen der Verbindung der richtige Pfad zu ihnen angegeben wird. Diese Funktion ist sehr nützlich, da Sie zuvor erstellte Schemata wiederverwenden und nur mit der gewünschten Struktur verbinden können.

Damit ist meine Überprüfung von JSON und JSON Schema abgeschlossen. Ich hoffe, dass das hier vorgestellte Material und die besprochenen Beispiele hilfreich sind, um die Funktionen von JSON Schema zu untersuchen.

Anstelle einer Schlussfolgerung


Ich denke, es ist Zeit, Bilanz zu ziehen. Was kann uns das JSON-Schema letztendlich geben?

  1. Dies kann Entwicklern das Leben erleichtern und den Code für die Validierung von JSON-Nachrichten verbessern.
    Mit anderen Worten, es vereinfacht die Softwareunterstützung und -integration.
  2. Ermöglicht die Entwicklung von Diensten, die Erarbeitung der Formate und der Zusammensetzung der Daten mit einer "Reserve" für die zukünftige Entwicklung des Systems.
  3. Wenden Sie die Überprüfung von Dokumenten in dokumentenorientierten, objektorientierten Datenbanken an.
  4. JSON-Schema kann helfen, Zeit beim Testen und Dokumentieren der API zu sparen.
  5. Vereinfachen Sie die Unterstützung der Abwärtskompatibilitäts-API.
  6. Ermöglicht die Verwaltung von Datenströmen.
  7. Flexible Validierung beim Generieren eines JSON-Schemas zur Laufzeit mit Werten in "enum", die in der Programmausführungsphase erhalten wurden.
    Es kann für eine Zustandsmaschine oder einen Workflow mit Status in "enum" verwendet werden (Anwendungsbeispiel vonTsdk und VolCh)
  8. Das JSON-Schema kann bei der Implementierung von DTO angewendet werden
    ( Anwendungsbeispiel vonamarkevich)

Jeder von uns entscheidet in seinen IT-Projekten, ob er ein JSON-Schema ist oder nicht. Oben habe ich eine Liste aufgeführt, die meiner Meinung nach den Hauptvorteil der Verwendung von Schaltkreisen darstellt, und um herauszufinden, was es bereits wert ist, über deren Anwendung in Projekten nachzudenken.

Vielleicht möchten mir die Leser helfen, diese Liste fortzusetzen?
Ich werde dankbar sein :) Ich werde

auch eine Liste von Links geben, die meiner Meinung nach nützlich für die Arbeit mit JSON und JSON Schema sind

  1. .
  2. .
  3. ().
  4. ( ).
  5. - JSON-Schema.
  6. JSON Schema
  7. JSON Schema , ( alemiks), angular ngx-schema-form, AJSF ( anotherpit).

Und ein Link zum Git-Repository, über das Sie sich mit den Quelldateien vertraut machen können, die in diesem Artikel zur Überprüfung bereitgestellt werden: ein Repository mit den Quelldateien der Beispiele .

Systemarchitektin,
© Irina Blazhina

All Articles