Creating and managing OCDS extensions
This post in our technical series explains how to create an OCDS extension. Versión en español.
One of the major developments in version 1.1 of the Open Contracting Data Standard (OCDS) is full support for schema extensions. Extensions describe additional fields of data beyond those covered by the core standard and can be useful for documentation and validation of advanced data that helps users to understand contracting processes in more detail.
The structure of extensions
Each extension consists of:
- Documentation explaining the use case for the additional fields, and how they should be interpreted;
- A JSON merge-patch against the schema introducing the technical definition of new fields; and/or
- New or updated codelists; and
- An extension definition (extension.json) file that describes the extension.
You can see the standard extension template here, and a range of example extensions here.
Using extensions
The documentation for each extension will explain the fields that it introduces and provide definitions for each. Publishers can simply include these fields in their OCDS files, and then declare that they are using the extension, in order for the data to be validated.
To declare the use of an extension publishers should include a link to the ‘extension.json’ file in the extensions array of a release or record package file.
For example, a publisher using the lots (core) extension because their tenders involve lots, and the community documentation extension which supports page numbers for linked documents, would start their release package like this:
{ "version":"1.1", "extensions":[ "https://raw.githubusercontent.com/open-contracting /ocds_lots_extension/v1.1/extension.json", "https://raw.githubusercontent.com/open-contracting /ocds_documentation_extension/master/extension.json" ], "releases":["..."] }
This information is understood by the official OCDS validator, which will:
- Display links to documentation for each extension – supporting users who want to interpret the data;
- Fetch and apply each extension to the OCDS schema – checking that extensions are themselves valid in the process, and providing an extended schema for download for use in local validation workflows.
- Validate supplied data against the extended schema – allowing publishers to check that their extended data has been correctly structured.
Third-party tools can also use the extensions array in a release or record package to detect when incoming data includes specific additional features, such as lots or locations, and can adapt how they process the data accordingly.
Developing an extension
To develop an extension you will need an understanding of how to write JSON Schema and an understanding of the underlying structure of the OCDS Schema. Extensions consist of fragments of JSON Schema which are merged into the main OCDS schema files to create an extended schema.
Example
The partyScale extension adds a simple ‘scale’ property to the Organization object, which is used to define entries in the parties array. In the partyScale repository there is a README.md file that defines the behaviour of the extension, and a release-schema.json file that provides JSON schema for the additional fields as below:
{ "definitions": { "Organization": { "properties": { "details":{ "properties":{ "scale":{ "title":"Scale", "description":"For commercial organization's, is this a micro (micro), Small or Medium Enterprise (sme) or large (large) entity according to the definitions used by the procuring entity or buyer. This field can be left blank if no such concepts apply.", "type":["string","null"], "enum": ["micro","sme","large",""] } } } } } } }
Note that, as this is provided using the JSON merge patch model, we include all the parent hierarchy, even though we are only introducing ‘scale’, so that any tool applying the patch knows where to place this new entry.
Process
The process to develop an extension starts with discussion before moving to an iterative process of development, documentation, and demonstration.
Step 1: Discuss
After checking the current list of extensions and discovering your need is not met by one of these, you should search open and closed issues in the OCDS Standard issue tracker to make sure no one is already working on a related extension. If they are, consider getting in touch with them to collaborate. If they are not, create a new issue to describe the extension you plan to create, setting out the need that it meets, and giving as much information as you can about your current plans for modeling the data. A few tips to create a good issue are:
A description of the process you are trying to represent. Avoid too much detail about the data: describe the workflow and the information that people know at particular points in time. A diagram can help here.
Examples of existing data. Ideally, find two or three different examples of how this data is currently represented, to help with data modeling.
What belongs in OCDS, and what could belong in secondary datasets. For example, some budget and corporate information is better represented in separate datasets, as they are independent of individual contracting processes.
A description of the use cases for this data. In particular: Is there a strong use case for comparing between countries? Is the main use case creating common interfaces? This will inform the balance between interoperable abstraction versus direct representation of a publisher’s data.
For example, if three countries have similar but not identical processes, we may prefer an abstracted model that can represent all three, and which would provide enough information that the same interface could display ‘good enough’ information for each (i.e. interfaces wouldn’t need major customization to display the data correctly).
On the other hand, if the countries have very different processes, we should assume that any interfaces or analyses will need to be customized for each country. In such cases, we want to be careful with abstraction, because it adds complexity for the publisher and the user to convert between reality and the abstracted model.
Throughout the development of your extension, keep this issue updated. This provides an opportunity for others with an interest in the same or similar data to get involved in shaping the chosen approach to data modeling.
Step 2: Develop
To develop your extension, you will first need to decide on field names and structures.
It can be useful to start by mocking up an example of the data you are creating an extension for in JSON format. You can then consider:
- How would different data fit into this structure?
- Are the field names intuitive for users?
- Is the structure easy for applications to consume?
At this stage, the more different examples of source data, and different use cases for the data you can consider, the better.
Once you have settled on a model, ideally with community feedback, you should then create the schema JSON merge patch. You can do this using the extension creator, or manually using the standard extension template.
There are also a number of OCDS schema conventions to consider:
- If the extension provides an array of objects, each object must include an id property.
- Use ‘Capitalised’ class names in the ‘definitions’ section.
- Use camelCase for all property names.
- English language field names should also be used for core and community extensions.
(The last two conventions can be relaxed for local extensions in cases where existing local properties are being inserted into OCDS data).
You will also need to find somewhere to host your extension online at a stable URL. GitHub provides a good option for this, as it also offers version control and issue tracking for your extension. Create a repository for your extension.
Step 3: Document
In parallel with the development of the extension schema, you will need to write a README file, and/or additional documentation.
A readme should consist of:
- An introduction providing a short description of the motivation for the extension;
- Definitions for all fields, matching the definitions provided in the schema itself;
- Examples of data that could be provided using the extension.
Step 4: Demonstrate
Before placing an extension in the extension registry, it is important to test it out.
Create a full example data file containing extended data, and submit it to the validator.
Extensions do not need to be in the registry before the validator will recognize them.
Tools
The OCDS extension creator simplifies the process of creating a JSON merge patch and standard extension folder structure.
It provides three schema views:
- Source – where you can select the base schema you are extending.
- Target – where you can edit the schema to the updated version that should result from your extension. Select ‘Copy from source above’ to populate this with the starting schema you have selected.
- Patch – which will show the difference between the source schema, and your update, providing the JSON merge patch. After editing ‘target’, click ‘Generate patch’ to see this in action.
The target view is editable via a tree structure or a code editor.
If you need a head start with working on what the schema for a particular fragment of JSON might look like, you may also find https://jsonschema.net/ provides some useful tools for generating template schema from example JSON.
Registering an extension
There are three kinds of extension:
- Core extensions describe recommended fields. If it is relevant and feasible to provide the information described by a core extension (such as location or bid information), publishers are encouraged to do so. These extensions are kept stable by being versioned along with the standard, and going through the standard governance process. This means they can only be introduced or updated with a new version of the standard.
- Community extensions describe common approaches to publishing optional fields. These may have been developed to model a common set of additional fields that publishers have, or to describe data required by a particular use case. Community extensions can be introduced and included in the extension registry at any time, allowing ongoing growth of the standard between version updates.
- Local extensions describe fields required by a single publisher or context and are used to document and validate the extra data that a publisher is including. Local extensions are not included in the extension registry.
Details of how to register an extension can be found in the Extension Registry GitHub documentation.
Crear y administrar extensiones OCDS
Esta publicación en nuestra serie técnica explica cómo crear una extensión OCDS.
Uno de los más grandes desarrollos de la versión 1.1 del Estándar de Contrataciones Abiertas (OCDS, por sus siglas en inglés) es el soporte completo para extensiones al esquema. Las extensiones se utilizan para describir campos adicionales de datos fuera de esos que ya se encuentran el núcleo del estándar y pueden ser útiles para la documentación y validación de datos avanzados que contribuyan a que los usuarios entiendan los procesos de contrataciones más detalladamente.
La estructura de las extensiones
Cada extensión consiste en:
- Documentación explicando el caso de uso de los campos adiciones y como deben de ser interpretados;
- Un JSON merge-patch contra el esquema introduciendo la definición técnica de los nuevos campos; y/o
- Listas de código nuevas o actualizadas; y
- Un documento de definición de extensión (extension.json) que describa la extensión.
Acceda al template de extensiones estándar aquí, y a una serie de ejemplos de extensiones aquí.
Utilizando extensiones
La documentación para cada extensión explica los campos que introduce y provee definiciones para cada uno. Los publicadores pueden simplemente incluir estos campos en sus documentos OCDS, y después decir que están utilizando la extensión, para que los datos sean estructuralmente válidos.
Para declarar el uso de una extensión, los publicadores deben de incluir un enlace al documento “extension.json” en el array de extensiones de un release o record package.
Por ejemplo, un publicador usando la extensión de los lotes (extensión del tipo core) porque sus licitaciones implican lotes, y la extensión de documentación del tipo comunitaria que soporta el uso números de página para documentos vinculados, comienzan su release-package de esta manera:
{ "version":"1.1", "extensions":[ "https://raw.githubusercontent.com/open-contracting /ocds_lots_extension/v1.1/extension.json", "https://raw.githubusercontent.com/open-contracting /ocds_documentation_extension/master/extension.json" ], "releases":["..."] }
El validador OCDS entiende esta información, y va a:
- Mostrar enlaces a la documentación de cada extensión – apoyando a los usuarios que quieren interpretar los datos
- Recoger y aplicar cada extensión al esquema OCDS – revisando que las extensiones sean estructuralmente válidas en el proceso, y proveyendo un esquema extendido para descargar y usar en flujos de trabajo de validaciones locales.
- Validar estructuralmente los datos contra el esquema extendido – permitiendo a los publicadores revisar que sus datos extendidos están estructurados correctamente
Las herramientas de terceros también pueden utilizar una lista de extensiones en un release o record package para detectar cuándo los datos entrantes incluyen campos adicionales, como lotes o ubicaciones, y pueden adaptar adecuadamente cómo se procesan los datos.
Desarrollando una extensión
Para desarrollar una extensión es necesario entender cómo escribir un esquema JSON y entender su estructura. Las extensiones consisten en fragmentos de esquema JSON que se fusionan en los documentos del esquema OCDS principal para crear un esquema extendido.
Ejemplo
La extensión partyScale añade una propiedad “scale” simple al objeto de Organización, que se utiliza para definir entradas en la lista de partes involucradas. En el repositorio de partyScale hay un documento README.md que define el comportamiento de la extensión, así como un documento release-schema.json que provee un esquema JSON para los campos adicionales como se muestra a continuación:
{ "definitions": { "Organization": { "properties": { "details":{ "properties":{ "scale":{ "title":"Scale", "description":"For commercial organization's, is this a micro (micro), Small or Medium Enterprise (sme) or large (large) entity according to the definitions used by the procuring entity or buyer. This field can be left blank if no such concepts apply.", "type":["string","null"], "enum": ["micro","sme","large",""] } } } } } } }
Tome en cuenta que como esto se provee con el modelo de JSON merge patch, en donde incluimos toda la jerarquía de elementos primarios aunque solo introducimos “scale”, así cualquier herramienta aplicando el parche sabrá dónde aplicar la nueva entrada
Proceso
El proceso de desarrollo de la extensión empieza con una discusión antes de antes de empezar un proceso iterativo de desarrollo, documentación y demostración.
Paso 1: Discutir
Después de revisar la lista actual de extensiones y corroborar que sus necesidades no están siendo cubiertas por una de estas, debería de buscar issues cerrados y abiertos en el rastreador de issues del Estándar OCDS para asegurarse de que alguien más no esté trabajando en una extensión similar. Si encuentra que alguien sí está trabajando en algo similar, por favor considere entrar en contacto con las personas para colaborar con ellas. Si no encuentra a nadie, cree un nuevo issue para describir la extensión que están planeando crear, estableciendo la necesidad que cubre y dando toda la información posible sobre sus planes para modelar los datos.
Algunos consejos para crear un buen issue son:
Describir el proceso que se está intentando representar, intenten evitar dar muchos detalles sobre los datos: describa el flujo de trabajo y la información que las personas saben en un momento particular. Un diagrama puede ayudar aquí.
Ejemplos de datos existentes: Idealmente, encuentre dos o tres ejemplos diferentes de cómo se representan los datos actualmente, para contribuir con el modelado de datos.
Qué pertenece a OCDS y que pertenece a bases de datos secundarias. Por ejemplo, alguna información de presupuestos e información corporativa estaría mejor representada en bases de datos separadas, ya que son independientes de los procesos de contrataciones individuales.
Una descripción de los casos de uso de estos datos. En particular: Existe un caso de uso fuerte para comparación entre países? Cuál es el principal caso de uso de crear una interfaz común? Esto va a informar sobre el balance entre una abstracción interoperable contra una representación directa de los datos del publicador.
Por ejemplo, si tres países tienen procesos similares pero no idénticos, se puede preferir un modelo abstracto que representa los tres, y que den suficiente información para que la misma interfaz pueda enseñar información lo suficientemente buena para cada uno (e.j. La interfaz no necesitaría una gran personalización para mostrar los datos de forma correcta).
Por el otro lado, si los países tienen procedimientos muy diferentes, se puede asumir que cualquier interfaz o análisis tendría que ser personalizado para cada país. En esos casos, se tiene que tener cuidado con la abstracción, porque añade complejidad para el publicador y el usuario para convertir entre la realidad y el modelo abstracto.
A través del desarrollo de la extensión, es necesario mantener actualizado el issue. Esto da oportunidad a otras personas con un interés similar o datos similares de involucrarse en crear el método en que se van a modelar los datos.
Paso 2: Desarrollo
Para desarrollar su extensión, primero necesita decidir los nombres y estructuras de los campos.
Puede ser útil empezar a hacer un muestreo de los datos para los que se está creando una extensión en un formato JSON. Así puede considerar:
- Cómo pueden diferentes datos ajustarse a esta estructura?
- Los nombres de los campos son intuitivos para los usuarios?
- Son las estructuras fáciles de consumir por aplicaciones?
En este punto, mientras más diferentes sean los ejemplos de los datos fuente y los diferentes casos de uso para los datos que pueda considerar, es mejor para la creación de su extensión.
Una vez que haya decidido un modelo, idealmente con retroalimentación de la comunidad, deberá crear un JSON merge patch de esquema JSON. Puede hacer esto usando el creador de extensiones, o manualmente utilizando el template de extensiones del estándar.
Existen también un número de convenciones del esquema OCDS a considerar:
- Si la extensión provee un array de objetos, cada objeto debe incluir una propiedad id.
- Usar nombres de clase capitalizados en la sección definiciones
- Usar camelCase para todos los nombres de propiedad
- Deben usarse campos con nombre en inglés para las extensiones del tipo core y comunitarias.
(Las últimas dos convenciones pueden ser menos estrictas para extensiones locales en caso de que existan propiedades locales insertadas en los datos OCDS).
También necesitará encontrar un lugar para alojar su extensión en línea con una URL estable. GitHub es una buena opción para esto, ya que también ofrece un control de versiones y un rastreo de issues para su extensión. También debe de crear un repositorio para su extensión.
Paso 3: Documentar
En paralelo con el desarrollo del esquema de extensión, necesita escribir un documento README y/o documentación adicional.
Un readme deberá consistir de:
- Una introducción con una descripción corta del motivo de la extensión
- Definiciones para todos los campos, que sean iguales a las definiciones que se dan en el esquema
- Ejemplos de datos que pueden resultar del uso de la extensión
Paso 4: Demostración
Antes de poner una extensión en el registro de extensiones, es importante probarla.
Crear un documento ejemplo que contenga todos los datos extendidos, y utilizar el validador.
Las extensiones no necesitan estar en el registro para que el validador las reconozca.
Herramientas
El creador de extensiones OCDS simplifica el proceso de crear un JSON merge patch y una estructura para la carpeta de la extensión estándar.
Da tres vistas del esquema:
- Fuente- donde se puede seleccionar el esquema base que se extenderá
- Objetivo- donde se puede editar el esquema con la versión actualizada que resulta de la extensión. Seleccione “Copiar de la fuente” para poblar esto con el esquema inicial que ha seleccionado.
- Parche- Mostrará la diferencia entre el esquema fuente y su actualización, dando un JSON merge patch. Después de editar “target”, de click en “Generate patch” para generar el parche. La vista objetivo es editable por medio de una estructura de árbol o un editor de código.
Si necesita un ejemplo inicial para trabajar en cómo una extensión de un fragmento de JSON en particular debe de verse, puede encontrar que https://jsonschema.net/ tiene herramientas útiles para generar esquemas de ejemplos JSON.
Registrar una extensión
Existen tres tipos de extensiones:
- Las Extensiones core se utilizan para describir campos recomendados. Si es relevante y factible dar la información descrita por una extensión core (como lugar o información de oferta), los publicadores están alentados a hacerlo. Estas extensiones se mantienen estables al ser versionadas con el estándar, y al pasar por el proceso de gobernanza estándar. Esto significa que sólo pueden introducirse o actualizarse con una versión nueva del estándar.
- Las extensiones de comunidad o comunitarias describen métodos comunes para publicar campos adiciones. Estas se pudieron haber desarrollado para modelar un conjunto común de campos adicionales que tengan los publicadores, o que describan los datos requeridos por un caso en particular. Las extensiones de comunidad se pueden introducir e incluir en el registro de extensión en cualquier momento, permitiendo el continuo crecimiento del estándar entre actualizaciones de versión.
- Las extensiones locales describen campos adicionales requeridos por un solo publicador o contexto y que son utilizadas para documentar y validar datos extras que el publicador está incluyendo. Las extensiones locales no se encuentran en el registro de extensiones.
Los detalles de cómo registrar una extensión se encuentran en la documentación del Registro de Extensiones GitHub.