OpenAPI contract to HTML
2023-01-05
The open API contract is a standard it's a standard it's a generally a big json or yaml file and people usually use it for documentation. But that contract contains a lot of that information that can enable your UI to automate building a web form.
If you look at the API structure, you’ll see the paths section:
"paths": {
"/v1/pages/{pagesId}": {
"post": "requestBody": {
"description": "Base object to post to pages",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/pages"
}
}
}
This allows you to find the individual API objects that we're going to interact with; for example, if I wanted to read one of the pages in my blog I go to /v1/pages/{pagesID}. In this example I’m looking at the requestBody for a POST object, but really what I’m looking for is the core schema for my “pages” object.
The OpenAPI specification allows you to define your schema in the path object, but it's best practice to actually use a reference and to share that reference with your GET, POST and PUT methods. The reference is described as “$ref” and the path is “#/components/schemas/{object key}” – in this cae it’s “pages” because I like consistency.
I use a little javascript to split the reference path and turn it into a javascript object:
ref = ref.replace(/\\\\//g, '"\\\]\\\["');
ref = ref.replace('#"\\\]', '');
ref = 'contract' + ref + '"\\\]';
which effectively turns the string #/components/schemas/pages into contract[components][schemas][pages] that I can use to access the object directly.
Now we find the properties of the API object:
"components": {
"schemas": {
"pages": {
"title": "The request and base object for pages",
"type": "object",
"properties": {
"pagesname": {
"type": "string",
"format": "text",
"example": "This is a blog",
"minLength": 0,
"maxLength": 500000
},
"pagesbody": {
"type": "string",
"format": "markdown",
"example": "#Markdown\\\\\\\\n\\\\\\\\nI love \\\*markdown\\\*",
"minLength": 0,
"maxLength": 100000
},
"socialimage": {
"type": "string",
"format": "image",
"example": "https://uxapi.io/images/vodka-martini.jpg",
"minLength": 0,
"maxLength": 100000
},
These properties include things like the field names so I know “pagesname” is one of the fields I'm going to want to format. I also know that the type is a string, although the type field is part of the open API specification and is fairly limited, but there's also this format which you can use for different things. The “pagesname” format is listed as text, but if you look at the “pagesbody” field it’s defined as “markdown” which tells me that I can render this in a rich text editor that saves as markdown (I use ckeditor for markdown editing and showdown.js for rendering),
If you look at the kind of format for the “socialimage” you can see the type is a string there but there is also a maximum length of 100K because I may want to be able to store the image directly as a base64 encoded data string and this helps limit too large of fields being stored in the object, and allows you to trigger a warning if your consumer is trying to post something too big.
Regardless of whether it's a URL or not I can take a look at this schema and I can render it to a web form automatically just based on the field names and the formats and it's all right there in the contract so there's no reason for me to constantly reinvent the wheel every time I want to build a web form I just read the information from the contract which is our source of truth.
Be sure to take a peek at my UXAPI Editor library on github – it’s all built around my API as a Service platform and assumes a lot of standards are being followed in the API contract, but it can give you an idea of how things might work.