How to declare ORM model and validation rules in OpenAPI doc for Golang

Golang OpenAPI ORM

The typical usage mode of an OpenAPI document is generating client and server API skeletons and interfaces from model. In most cases, the generated types aren’t compatible with the DB schema, so adapters must be implemented which causes more coding and automatic tests.

A few solution provides the internal types on the external API, so adapters between internal and external types aren’t needed (for example Kubernetes). This article explains how it can be done in Go with GORM.

GORM is an ORM implementation in Go. The DB schema information can be defined as struct tags, for example:

type Meal struct {
Id int64 `gorm:"primaryKey"`
Ingredients []Ingredient `gorm:"many2many:meal_ingredients"`

This kind of information should be defined in OpenAPI document, but the official specification does not offer an opportunity for it. The OpenAPI spec gives only the x- extension properties, which the generators may process as it declare. A few generator supports it for struct tags by different ways. This ways can be used for declaring another struct tags, for example additional validator rules (if the OpenAPI validation rules aren’t enough), for example:

type Meal struct {
Name string `valid:"customNameValidator"`

If the internal and external types are same, only a subset of OpenAPI and GORM possibilities can be used. For example, the type should be same for Get and CRUD OpenAPI operations. The missing rules must be validated in the service implementation (for example the Id field for Create and Update operations).
Another limitation is declaring the optional values. Most of Go generators declare the optional fields as reference type (pointer), because the zero values (0, “”) are used as optional value by a lot of Go libraries. So the zero value must be handled carefully (for example change a non-zero value to zero value by Update operation). GORM can be forced to update zero values by .Select("*").Update clause.

This article describes one alternative for OpenAPI V2 and one for OpenAPI V3. Many-to-many relationship is more complex than a simple reference, so this kind of relationships are also explained:

Many-to-many relationship

The selected DB is PostgreSQL, which supports array field type, so additional table for many-to-many relationship isn’t needed.