Esquema JSON. Ser o no ser?

Arquitectura: el arte de hacer innecesariamente necesario.

Frederick Kiesler

Para nadie es un secreto que para cualquier servicio web que utilice el protocolo SOAP en formato XML, una solución confiable y probada en el tiempo es el desarrollo preliminar del Esquema XML ( esquema xsd), que describe los tipos de datos y la estructura de los mensajes XML. Con este enfoque, los desarrolladores tienen una clara ventaja: tienen reglas estrictas y estandarizadas para la estructura de los mensajes que se establecen en el esquema, el número de reglas es finito y le permiten automatizar la verificación de cualquier mensaje nuevo en formato XML.

Pero también se sabe que el lenguaje XML ha sido suplantado por el lenguaje de marcado JSON (JavaScript Object Notation) debido a su mayor peso (peso XML), así como a la difusión del estilo arquitectónico del desarrollo de software REST (REpresentational State Transfer) para sistemas distribuidos. Aunque el estilo REST en sí no requiere el uso de JSON (se puede decir que no requiere nada en absoluto, sino que "recomienda"), pero como muestra la práctica, más a menudo cuando se desarrolla una API REST, JSON se usa para describir el cuerpo de los mensajes.

Por lo tanto, la práctica de desarrollar una API REST con mensajes JSON ha entrado firmemente en la vida de TI en Rusia (y no solo en la nuestra), aunque la experiencia en la descripción de la estructura del mensaje en forma de esquema XML ha simplificado enormemente la vida de los desarrolladores de servicios web en un momento dado, ignorado persistentemente en el caso de mensajes JSON. Pero no todos los que no pueden sino alegrarse.

Cuando los desarrolladores familiarizados con el Esquema XML enfrentaron la necesidad de reinventar la rueda cada vez con el análisis de documentos y reinventar la lógica de validación, se formó un borrador de esquema JSON similar . Está disponible en json-schema.org, así como una serie de documentos sobre el historial de cambios y ejemplos de uso. Y a pesar del hecho de que se publica en estado borrador, ha sido respaldado por todas las plataformas y bibliotecas de desarrollo populares en diferentes idiomas. JSON esquema

en sí ofrece menos posibilidades de estructuración mensaje de que el Esquema XML . Lo que se puede describir fácilmente a través del Esquema XML no siempre será una tarea trivial para repetir utilizando el Esquema JSON, si es posible. Pero aquí consideraría este hecho como una ventaja. ¿Por qué? Se sabe que cuanto más simple y lineal es el algoritmo del sistema, más confiable es, más simple es la estructura del documento, más fácil es para la percepción, etc. No puedo evitar citar:



"Todo lo ingenioso es simple, y todo lo simple es ingenioso" . Y si no es posible describir la estructura compleja del documento y el conjunto de opciones aceptables utilizando el esquema, entonces quizás valga la pena mirar en la dirección de simplificar la estructura y la lógica de la formación de este documento.

Prefacio


Entonces, ¿de qué trata este artículo?

Me gustaría llamar más la atención sobre los beneficios de describir los mensajes JSON transmitidos por el esquema JSON. A pesar del hecho de que "en la entrada", desarrollar una API REST sin ningún esquema JSON es siempre más simple y rápido, pero con el crecimiento del sistema, su ausencia de una forma u otra conduce a un aumento en el costo de mantenimiento y soporte del sistema. Además, cualquier estudio preliminar de la estructura del mensaje contribuye a una mejor organización del intercambio de mensajes, sin duplicación innecesaria en el intercambio de datos y reglas generales para su procesamiento.

Además, para difundir información en la comunidad de habla rusa sobre las posibilidades del esquema JSON y las reglas para trabajar con él, compartiré mi experiencia con ejemplos específicos en el marco de este artículo.

Formulación del problema


Antes de comenzar a estudiar JSON y JSON Schema, describiré la tarea en la que consideraremos todos los ejemplos a continuación.

Considere un modelo de gestión de roles en una organización. Suponemos que necesitaremos transferir información de referencia sobre el modelo a seguir a sistemas dependientes en mensajes en formato JSON llamando a un servicio REST.

Descripción de la tarea:

la organización tiene empleados, a menudo tienen que trabajar simultáneamente en varios sistemas. Al mismo tiempo, el nivel de acceso (autoridad) a uno u otro componente (recurso) del sistema para diferentes empleados, dependiendo de su rol en la organización, puede diferir y debe controlarse durante la autorización del usuario en el sistema.

Por ejemplo, un contador (rol) tendrá acceso de lectura y edición (operaciones / credenciales) a las nóminas (recurso) para los salarios de todos los empleados, y un analista (rol), por ejemplo, tendrá acceso de lectura (operación / credenciales) solamente de acuerdo con su recibo de sueldo (recurso).

Es necesario diseñar y describir un modelo de gestión de roles en una organización. Los roles disponibles, un conjunto de poderes y recursos posibles en el sistema deben transferirse a otros sistemas a pedido.


Figura 1. Presentación de los componentes del modelo a seguir Los

métodos para describir e implementar el modelo a seguir pueden diferir, pero independientemente de la implementación, con mayor frecuencia en el modelo a seguir en este caso, podemos distinguir los siguientes componentes básicos:

  1. Rol (por ejemplo, gerente, contador, etc.).
  2. Recurso (por ejemplo, documento, propiedad, etc.).
  3. Operación / autoridad (por ejemplo, leer, imprimir, crear, etc.).

Al describir el acceso basado en roles (como una de las opciones posibles), recurren a la creación de una matriz de acceso discreta basada en entidades seleccionadas, por ejemplo:

Tabla 1. Matriz de acceso discreto.
Recurso: documentosRecurso: objetos
Rol: gerenteleer, imprimirleer, crear
Rol: contadorleer, crearleer

Más adelante en el artículo, primero nos familiarizaremos con el componente teórico del formato de texto para intercambiar datos JSON y las reglas para estructurarlos usando el esquema JSON, y como ejemplos, describiré las entidades de entidad para los roles, recursos y operaciones en el lenguaje JSON y sus esquemas JSON dentro de nuestro Establecer tarea.

Notación de objetos JavaScript (JSON)


JSON (notación de objetos JavaScript en inglés) es un formato de intercambio de datos basado en texto basado en JavaScript.

Teoría


El lenguaje de marcado JSON define un conjunto limitado de tipos de datos. Para el par {"clave": valor} para la "clave" siempre use la cadena de tipo, para el "valor" los tipos son aplicables: cadena, número, objeto (tipo JSON), matriz, booleano (verdadero o falso) y nulo.


Figura 2. Tipos de datos JSON

La figura muestra los tipos básicos y ejemplos de su uso. Bastante simple, en mi opinión.

La sintaxis JSON es un subconjunto de la sintaxis de JavaScript, donde:

  1. Los datos se escriben como pares {"clave": valor}.
  2. Los datos están separados por comas.
  3. Los corchetes registran objetos.
  4. Las matrices se escriben entre corchetes.
  5. Los nombres de las "claves" distinguen entre mayúsculas y minúsculas.


Figura 3. Sintaxis JSON

Práctica


Considere un ejemplo de un directorio de roles que transferiremos en el servicio:


Figura 4. Descripción de un directorio de roles en formato json

A partir del ejemplo, se puede ver que incluso a pesar de un número tan pequeño de tipos básicos, cuando se combinan, podemos crear estructuras de mensajes más complejas si es necesario. Aquí, en particular, describo el directorio de roles a través de un objeto de matrices que contienen otros objetos (en la figura 4 están resaltados por dos rectángulos).

En forma tabular utilizando las herramientas de visualización json, el directorio se puede representar de la siguiente manera:


Figura 5. Visualización del directorio de roles en formato JSON

El directorio, en términos relativos, representa 3 "tablas" para asignar roles en un grupo de administradores, contadores y trabajadores. La composición de los "atributos" se puede ampliar, si es necesario.

La representación visual, en mi opinión, simplifica la percepción de la descripción del texto. Estableceremos una estructura similar para los otros dos directorios. Daré a continuación un ejemplo de solo una vista de tabla para un directorio de autoridad (operaciones) y recursos.


Figura 6. Visualizaciones del directorio de permisos en formato JSON


Figura 7. Visualizaciones del directorio de recursos en formato JSON Los

mensajes de origen en formato de texto JSON para el directorio de roles , recursos y permisos se pueden descargar / ver desde el enlace .
Ahora pasemos a lo más interesante: ¡estudiar el esquema JSON y crear un esquema para nuestros libros de referencia!

Esquema JSON


Teoría


Dado que el esquema json está escrito en formato JSON, admite todos los tipos JSON más la adición: el tipo entero, que es un subtipo del tipo de número. El esquema en sí es un objeto JSON y está destinado a describir datos en formato JSON. El siguiente es un esquema de los tipos de datos utilizados para crear el esquema en sí:


Figura 8. Tipos de datos del esquema JSON

Como puede ver en la figura, el esquema usa los mismos tipos de datos, así como los mismos principios de sintaxis que para un documento JSON normal, que se muestra en figura 3.

Ahora consideraremos lo más importante: las reglas utilizadas en el esquema para establecer restricciones y estructurar mensajes JSON.

El esquema JSON le permite:

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

Algunas "palabras clave" son puramente descriptivas, como: "título", "descripción", etc., que simplemente describen el propósito del esquema. Otros se utilizan para identificar el documento: "$ esquema". Esta palabra clave se usa para indicar la versión deseada del esquema. El valor de esta palabra clave debe ser una cadena que represente un URI, por ejemplo: "$ esquema": " json-schema.org/draft-04/schema# ".

Es muy importante tener en cuenta aquí que no todas las versiones pueden ser compatibles con su herramienta de circuito. Pero el 4º borrador es apoyado por casi todos. Los últimos cambios (JSON Schema 2019-09 Release Notes) para diferentes versiones se pueden encontrar en json-schema.org/draft/2019-09/release-notes.html .

Las palabras clave restantes se usan directamente para validar el documento JSON. Ahora los consideraremos.

Tabla 2. Análisis de la estructura del esquema JSON. Palabras clave y sus ejemplos de uso.
Un tipoPalabra (s) claveEjemplo / Descripción
"Palabras clave" para describir el esquema"$schema"
"$schema": http://json-schema.org/draft-04/schema#

Se utiliza para configurar la versión borrador del esquema.
"$id"
"$id": "http://archi-blair.com/schemas/RolesDictionaryDef.json#"

Se usa para indicar un identificador único para un documento o sus subcircuitos.
"title"
"description"
"examples"
"comment"

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

"Palabras clave de validación" generales independientes del tipo de datos del elemento"enum"
{"enum": [ "administrator", "superuser" ]}

Se realiza una comprobación para que coincida con al menos 1 valor.
"const"
{"const": "user" }

Se realiza una verificación para el cumplimiento exacto del valor establecido.
"type"
{"type": ["number", "string", "null", "boolean"]}
{"type": "array"}

Especifica el tipo de datos que usará el esquema. Esta palabra clave es opcional, y el valor de la palabra clave puede ser una cadena que representa un tipo de datos válido o una matriz de cadenas que representan tipos de datos válidos.
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"

, .
, .

Examinamos las palabras clave del esquema JSON, que nos permiten describir la estructura futura de nuestros mensajes en formato JSON.

Aquí puede encontrar más ejemplos de uso de palabras clave.

Práctica


Al considerar ejemplos de esquemas JSON completos, procederemos de manera similar a ejemplos de trabajar con mensajes en el formato JSON. Aquellos. Utilizaremos la representación visual en forma de árbol y de tabla para nuestros esquemas de directorios de roles, recursos y autoridades (operaciones), y con el texto de los esquemas que propongo leer a los lectores interesados ​​por su cuenta en git .

El siguiente es un diagrama para una referencia de roles.


Figura 9. Ejemplo de esquema JSON para el directorio de roles

Como vemos en la figura, el esquema es un objeto JSON y describe nuestro mensaje para transmitir el directorio de roles en JSON, que se mostró en la Figura 4. En el ejemplo actual, se puede mostrar cómo usar el esquema JSON Se describe un objeto de matriz que consta de objetos.

Los esquemas de los otros dos directorios (autoridad y recursos) son idénticos en estructura al esquema para el directorio de roles, por lo que no los daré aquí, pero daré un esquema que combina los 3 directorios.

Desafortunadamente, el esquema de todo el directorio durante la expansión no cabe en la pantalla, por lo que consideraremos parte de él.


Figura 10. Un ejemplo de un directorio de esquema JSON que combina un directorio de roles, permisos y recursos

En la figura, vemos que algunos de los objetos en la matriz de directorios están conectados usando la palabra clave "anyOf".

Además, quizás, una representación tabular del directorio será más visual.

Considere otra característica importante de nuestro esquema:


Figura 11. Un esquema JSON de ejemplo de un directorio que combina un directorio de roles, permisos y recursos en una vista de tabla

De la figura vemos que un directorio de combinación no duplica el código de directorios previamente desarrollados de roles, permisos y recursos, sino que usa la palabra clave "$ ref "

Los directorios considerados en los ejemplos están en el mismo directorio, pero, si es necesario, esta regla no se puede observar, pero se puede colocar en diferentes directorios, lo que indica la ruta correcta a ellos al conectarse. Esta característica es muy útil, ya que le permite reutilizar esquemas creados previamente, solo conectándolos a la estructura deseada.

Esto concluye mi revisión de JSON y JSON Schema. Espero que el material presentado aquí y los ejemplos discutidos sean útiles para explorar las capacidades del esquema JSON.

En lugar de una conclusión


Creo que es hora de hacer un balance. Entonces, ¿qué nos puede dar el esquema JSON?

  1. Puede facilitar la vida de los desarrolladores y mejorar el código para validar los mensajes JSON.
    En otras palabras, simplifica el soporte y la integración del software.
  2. Le permite desarrollar servicios, resolviendo los formatos y la composición de los datos con una "reserva" para el desarrollo futuro del sistema.
  3. Aplique la verificación de documentos en bases de datos orientadas a documentos y orientadas a objetos.
  4. JSON-Schema puede ayudar a ahorrar tiempo probando y documentando la API.
  5. Simplifique la compatibilidad con API de compatibilidad con versiones anteriores.
  6. Le permite administrar flujos de datos.
  7. Validación flexible al generar el esquema JSON en tiempo de ejecución con valores en "enum" obtenidos en la etapa de ejecución del programa.
    Se puede usar para una máquina de estado o flujo de trabajo con estados en "enum" (ejemplo de aplicación deTsdk y VolCh)
  8. El esquema JSON se puede aplicar en la implementación de DTO
    (ejemplo de uso deamarkevich)

Cada uno de nosotros decide "Ser o no ser el esquema JSON" en nuestros proyectos de TI. Arriba, di una lista de lo que considero la ventaja clave de usar circuitos, y por el bien de lo que ya vale la pena pensar sobre su aplicación en proyectos.

¿Quizás los lectores querrán ayudarme a continuar esta lista?
Estaré agradecido :)

También daré una lista de enlaces, en mi opinión, útiles para trabajar con JSON y JSON Schema

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

Y un enlace al repositorio git, donde puede familiarizarse con los archivos fuente proporcionados para su revisión en este artículo: un repositorio con los archivos fuente de los ejemplos .

Arquitecto de sistemas,
© Irina Blazhina

All Articles