Schéma JSON. Être ou ne pas être?

Architecture: l'art de rendre inutilement nécessaire.

Frederick Kiesler

Ce n'est un secret pour personne que pour tout service Web utilisant le protocole SOAP au format XML, une solution fiable et éprouvée est le développement préliminaire du schéma XML ( schéma xsd) décrivant les types de données et la structure des messages XML. Avec cette approche, les développeurs ont un avantage évident: ils ont des règles standardisées strictes pour la structure des messages qui sont définis dans le schéma, le nombre de règles est fini et ils vous permettent d'automatiser la vérification de tout nouveau message au format XML.

Mais il est également connu que le langage XML a été supplanté par le langage de balisage JSON (JavaScript Object Notation) en raison de sa plus grande lourdeur (lourdeur XML), et également en raison de la propagation du style architectural du développement logiciel REST (REpresentational State Transfer) pour les systèmes distribués. Bien que le style REST lui-même ne nécessite pas l'utilisation de JSON (on peut dire qu'il ne nécessite rien du tout, mais «recommande»), mais comme le montre la pratique, plus souvent lors du développement d'une API REST, JSON est utilisé pour décrire le corps des messages.

Ainsi, la pratique de développer une API REST avec des messages JSON est fermement entrée dans la vie de l'informatique en Russie (et pas seulement la nôtre), bien que l'expérience dans la description de la structure des messages sous forme de schéma XML ait considérablement simplifié la vie des développeurs de services Web à un moment donné, constamment ignoré dans le cas des messages JSON. Mais pas tous ceux qui ne peuvent que se réjouir.

Lorsque les développeurs familiarisés avec le schéma XML ont dû à chaque fois réinventer la roue avec l'analyse de documents et réinventer la logique de validation, un projet de schéma JSON similaire a été formé . Il est disponible sur json-schema.orgainsi qu'un certain nombre de documents sur l'historique des changements et des exemples d'utilisation. Et malgré le fait qu'il soit publié sous forme de projet, il a longtemps été pris en charge par toutes les plates-formes de développement et bibliothèques populaires dans différentes langues. Le schéma JSON

lui-même offre moins de capacités de structuration des messages que le schéma XML . Ce qui peut être facilement décrit via le schéma XML ne sera pas toujours une tâche triviale à répéter en utilisant le schéma JSON, si possible. Mais ici, je considérerais ce fait comme un avantage. Pourquoi? On sait que plus l'algorithme du système est simple et linéaire, plus il est fiable, plus la structure du document est simple, plus il est facile à percevoir, etc. Je ne peux pas m'empêcher de citer:



"Tout ce qui est ingénieux est simple, et tout ce qui est simple est ingénieux . " Et s'il n'est pas possible de décrire la structure complexe du document et l'ensemble des options acceptables à l'aide d'un schéma, alors peut-être vaut-il la peine de chercher à simplifier la structure et la logique de la formation de ce document?

Préface


De quoi parle cet article?

Je voudrais attirer davantage l'attention sur les avantages de la description des messages JSON transmis par le schéma JSON. Malgré le fait que «à l'entrée», développer une API REST sans aucun schéma JSON soit toujours plus simple et plus rapide, mais avec la croissance du système, son absence d'une manière ou d'une autre entraîne une augmentation des coûts de maintenance et de support du système. De même, toute étude préalable de la structure des messages contribue à une meilleure organisation de l'échange des messages, sans double emploi inutile dans l'échange des données et des règles générales pour leur traitement.

Aussi, afin de diffuser des informations dans la communauté russophone sur les possibilités du schéma JSON et les règles de travail avec lui, je partagerai mon expérience avec des exemples spécifiques dans le cadre de cet article.

Formulation du problème


Avant de commencer à étudier le JSON et le schéma JSON, je décrirai la tâche sur laquelle nous considérerons tous les exemples ci-dessous.

Considérons un modèle de gestion des rôles dans une organisation. Nous supposons que nous devrons transférer des informations de référence sur le modèle de rôle existant vers des systèmes dépendants dans des messages au format JSON en appelant un service REST.

Description de la tâche:

L'organisation a des employés, ils doivent souvent travailler simultanément dans plusieurs systèmes. De plus, le niveau d'accès (autorité) aux différents composants du système (ressources) pour différents employés, selon leur rôle dans l'organisation, peut différer et doit être contrôlé lors de l'autorisation des utilisateurs dans le système.

Par exemple, un comptable (rôle) aura un accès en lecture et en édition (opérations / informations d'identification) aux livres de paie (ressource) pour les salaires de tous les employés, et un analyste (rôle), par exemple, aura un accès en lecture (opération / informations d'identification) uniquement selon son bulletin de paie (ressource).

Il est nécessaire de concevoir et de décrire un modèle de gestion des rôles dans une organisation. Les rôles disponibles, un ensemble de pouvoirs et de ressources possibles dans le système doivent être transférés à d'autres systèmes sur demande.


Figure 1. Présentation des composants du modèle de rôle. Les

méthodes de description et de mise en œuvre du modèle de rôle peuvent différer, mais quelle que soit la mise en œuvre, le plus souvent dans le modèle de rôle dans ce cas, nous pouvons distinguer les composants de base suivants:

  1. Rôle (p. Ex. Gestionnaire, comptable, etc.).
  2. Ressource (par exemple, document, propriété, etc.).
  3. Opération / autorité (par exemple, lire, imprimer, créer, etc.).

Lorsqu'ils décrivent l'accès basé sur les rôles (comme l'une des options possibles), ils ont recours à la création d'une matrice d' accès discrète basée sur des entités sélectionnées, par exemple:

Tableau 1. Matrice d'accès discrète.
Ressource: documentsRessource: objets
Rôle: managerlire, imprimerlire, créer
Rôle: comptablelire, créerlis

Plus loin dans l'article, nous nous familiariserons d'abord avec la composante théorique du format de texte pour échanger des données JSON et les règles pour les structurer en utilisant le schéma JSON, et comme exemples je fournirai une description des entités de référence pour les rôles, les ressources et les opérations dans le langage JSON et leurs schémas JSON dans notre définir la tâche.

Notation d'objet JavaScript (JSON)


JSON (English JavaScript Object Notation) est un format d'échange de données basé sur du texte basé sur JavaScript.

Théorie


Le langage de balisage JSON définit un ensemble limité de types de données. Pour la paire {"clé": valeur} pour la "clé" utilisez toujours le type chaîne, pour la "valeur" les types sont applicables: chaîne, nombre, objet (type JSON), tableau, booléen (vrai ou faux) et null.


Figure 2. Types de données JSON

La figure montre les types de base et des exemples de leur utilisation. Assez simple, à mon avis.

La syntaxe JSON est un sous-ensemble de la syntaxe JavaScript, où:

  1. Les données sont écrites sous forme de paires {"clé": valeur}.
  2. Les données sont séparées par des virgules.
  3. Les accolades enregistrent les objets.
  4. Les tableaux sont écrits entre crochets.
  5. Les noms des "clés" sont sensibles à la casse.


Figure 3. Syntaxe JSON

Entraine toi


Prenons un exemple de répertoire de rôles que nous transférerons dans le service:


Figure 4. Description d'un répertoire de rôles au format json

D'après l'exemple, on peut voir que même en dépit d'un si petit nombre de types de base, une fois combinés, nous pouvons créer des structures de message plus complexes si nécessaire. Ici, en particulier, je décris le répertoire des rôles à travers un objet de tableaux contenant d'autres objets (sur la figure 4 sont mis en évidence par deux rectangles).

Sous forme tabulaire à l'aide des outils de visualisation json, le répertoire peut être représenté comme suit:


Figure 5. Visualisation du répertoire des rôles au format JSON

Le répertoire, relativement parlant, représente 3 «tables» pour attribuer des rôles dans un groupe d'administrateurs, de comptables et de travailleurs. La composition des «attributs» peut être élargie, si nécessaire.

La représentation visuelle, à mon avis, simplifie la perception de la description textuelle. Nous allons définir une structure similaire pour les deux autres répertoires. Je vais donner ci-dessous un exemple d'une vue de table uniquement pour un répertoire d'autorité (opérations) et de ressources.


Figure 6. Visualisation du répertoire des autorisations au format JSON


Figure 7. Visualisation du répertoire des ressources au

format JSON Les messages source au format texte JSON pour le répertoire des rôles , des ressources et des autorisations peuvent être téléchargés / consultés à partir du lien .
Passons maintenant au plus intéressant: étudier le schéma JSON et créer un schéma pour nos ouvrages de référence!

Schéma JSON


Théorie


Étant donné que le schéma json est écrit au format JSON, il prend en charge tous les types JSON plus l'ajout: le type entier, qui est un sous-type du type numérique. Le schéma lui-même est un objet JSON et est destiné à décrire des données au format JSON. Voici un schéma des types de données utilisés pour créer le schéma lui-même:


Figure 8. Types de données du schéma JSON

Comme vous pouvez le voir sur la figure, le schéma utilise tous les mêmes types de données, ainsi que les mêmes principes de syntaxe que pour un document JSON standard, illustré sur figure 3.

Nous allons maintenant considérer les plus importantes - les règles utilisées dans le schéma pour définir les restrictions et structurer les messages JSON.

Le schéma JSON vous permet de:

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

Certains "mots clés" sont purement descriptifs, tels que: "titre", "description", etc., qui décrivent simplement l'objectif du système. D'autres sont utilisés pour identifier le document: "$ schema". Ce mot-clé est utilisé pour indiquer la version souhaitée du schéma. La valeur de ce mot clé doit être une chaîne représentant un URI, par exemple: "$ schema": " json-schema.org/draft-04/schema# ".

Il est très important de noter ici que toutes les versions ne peuvent pas être prises en charge par votre outil de circuit. Mais le 4ème projet est soutenu par presque tout le monde. Les dernières modifications (JSON Schema 2019-09 Release Notes) pour différentes versions peuvent être trouvées sur json-schema.org/draft/2019-09/release-notes.html .

Les mots clés restants sont utilisés directement pour valider le document JSON. Nous allons maintenant les considérer.

Tableau 2. Analyse de la structure du schéma JSON. Mots-clés et leurs exemples d'utilisation.
Un typeMots clés)Exemple / Description
"Mots clés" pour décrire le schéma"$schema"
"$schema": http://json-schema.org/draft-04/schema#

Utilisé pour définir la version provisoire du schéma.
"$id"
"$id": "http://archi-blair.com/schemas/RolesDictionaryDef.json#"

Utilisé pour indiquer un identifiant unique pour un document ou ses sous-circuits.
"title"
"description"
"examples"
"comment"

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

"Mots clés de validation" généraux, indépendamment du type de données de l'article"enum"
{"enum": [ "administrator", "superuser" ]}

Une vérification est effectuée pour correspondre à au moins 1 valeur.
"const"
{"const": "user" }

Un contrôle est effectué pour le respect exact de la valeur définie.
"type"
{"type": ["number", "string", "null", "boolean"]}
{"type": "array"}

Spécifie le type de données que le schéma utilisera. Ce mot clé est facultatif et la valeur du mot clé peut être une chaîne représentant un type de données valide ou un tableau de chaînes représentant des types de données valides.
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"

, .
, .

Nous avons examiné les mots clés du schéma JSON, qui nous permettent de décrire la future structure de nos messages au format JSON.

Vous trouverez ici d'autres exemples d'utilisation de mots clés.

Entraine toi


Lorsque nous considérons des exemples de schémas JSON terminés, nous procéderons de la même manière que des exemples d'utilisation de messages eux-mêmes au format JSON. Ceux. nous utiliserons la représentation visuelle sous forme d'arbre et de tableau pour nos schémas de répertoires de rôles, de ressources et d'autorités (opérations), et avec le texte des schémas, je propose de lire les lecteurs intéressés par eux-mêmes dans git .

Voici un diagramme pour une référence de rôle.


Figure 9. Exemple de schéma JSON pour le répertoire de rôles

Comme nous le voyons dans la figure, le schéma est un objet JSON et décrit notre message de transmission du répertoire de rôles dans JSON, qui est illustré à la figure 4. Dans l'exemple actuel, il peut être montré comment utiliser le schéma JSON Un objet tableau constitué d'objets est décrit.

Les schémas des deux autres répertoires (autorité et ressources) sont de structure identique au schéma du répertoire de rôles, donc je ne les donnerai pas ici, mais je donnerai un schéma qui combine les 3 répertoires.

Malheureusement, le schéma de l'ensemble du répertoire pendant l'expansion ne tient pas à l'écran, nous allons donc en considérer une partie.


Figure 10. Exemple de répertoire de schéma JSON qui combine un répertoire de rôles, d'autorisations et de ressources

Dans la figure, nous voyons que certains des objets du tableau de répertoires sont connectés à l'aide du mot clé "anyOf".

De plus, une représentation tabulaire du répertoire sera peut-être plus visuelle.

Considérez une autre caractéristique importante de notre schéma:


Figure 11. Un exemple de schéma JSON d'un répertoire combinant un répertoire de rôles, d'autorisations et de ressources dans une vue de table

De la figure, nous voyons qu'un répertoire de combinaison ne duplique pas le code des répertoires de rôles, d'autorisations et de ressources précédemment développés, mais utilise le mot clé "$ ref "

Les répertoires considérés dans les exemples se trouvent dans le même répertoire, mais, si nécessaire, cette règle ne peut pas être respectée, mais peut être placée dans des répertoires différents, indiquant le chemin d'accès correct à ceux-ci lors de la connexion. Cette fonctionnalité est très utile, car elle vous permet de réutiliser des schémas créés précédemment, en les connectant uniquement à la structure souhaitée.

Ceci conclut mon examen de JSON et du schéma JSON. J'espère que le matériel présenté ici et les exemples discutés seront utiles pour explorer les capacités du schéma JSON.

Au lieu d'une conclusion


Je pense qu'il est temps de faire le point. Que peut donc nous apporter JSON Schema?

  1. Il peut faciliter la vie des développeurs et améliorer le code de validation des messages JSON.
    En d'autres termes, il simplifie la prise en charge et l'intégration des logiciels.
  2. Vous permet de développer des services, en définissant les formats et la composition des données avec une "réserve" pour le développement futur du système.
  3. Appliquer la vérification des documents dans des bases de données orientées document et objet.
  4. JSON-Schema peut vous aider à gagner du temps en testant et en documentant l'API.
  5. Simplifiez la prise en charge de l'API de compatibilité descendante.
  6. Vous permet de gérer les flux de données.
  7. Validation flexible lors de la génération du schéma JSON au moment de l'exécution avec des valeurs dans "enum" obtenues au stade de l'exécution du programme.
    Il peut être utilisé pour une machine à états ou un workflow avec des états dans "enum" (exemple d'application deTsdk et VolCh)
  8. Le schéma JSON peut être appliqué dans la mise en œuvre de DTO
    (exemple d' utilisation deamarkevich)

Chacun de nous décide «Etre ou ne pas être JSON Schema» dans nos projets informatiques. Ci-dessus, j'ai donné une liste de ce que je considère comme le principal avantage de l'utilisation des circuits, et pour ce qu'il vaut déjà la peine de penser à son application dans les projets.

Peut-être que les lecteurs voudront m'aider à continuer cette liste?
Je vous en serai reconnaissant :) Je

donnerai également une liste de liens, à mon avis, utiles pour travailler avec JSON et JSON Schema

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

Et un lien vers le référentiel git, où vous pourrez vous familiariser avec les fichiers source fournis pour examen dans cet article: un référentiel avec les fichiers source des exemples .

Architecte système,
© Irina Blazhina

All Articles