Skip to content

Prevent or customize Link objects of models and collections for better API documentation #2037

Open
@roncsak

Description

@roncsak

Hello there,
I'd like to document my API project and I am using org.springdoc:springdoc-openapi-starter-common and org.springdoc:springdoc-openapi-starter-webmvc-ui for doing so.
All the schemas in the generated OpenAPI 3.0.1 documentation, includes the schema called Links which follows:

"Link": {
  "type": "object",
  "properties": {
    "href": {
      "type": "string"
    },
    "hreflang": {
      "type": "string"
    },
    "title": {
      "type": "string"
    },
    "type": {
      "type": "string"
    },
    "deprecation": {
      "type": "string"
    },
    "profile": {
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "templated": {
      "type": "boolean"
    }
  }
}

Therefore it is visible in the Swagger UI, as well:
image

My concern with this is that I, as an API provider I don't want to create false hopes in my API consumers that for Links, all the properties (hreflang, title, etc) will be available. Based on this draft, href is the only REQUIRED property, the rest are OPTIONAL.

The thing is, that properties of a given Schema are generated based on the properties of the RepresentationModel (like below), but Link schema generation won't follows this approach. So it would be good, if properties of Link would be generated to the schema based on actual Link properties (or Annotations?) somehow.

@Entity
@Table(name = "customers")
public class Customer extends RepresentationModel<Customer> {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "customerId", nullable = false)
    private Long id;

    @Column(name = "name", nullable = false)
    @Schema(type = "string", example = "My fine ass Company")
    public String name;

//  ... constructors, getters and setters ... 

Also, that would mean, that I might not want a dedicated Link schema because for my Customer object I would like to have href and name properties but for a different object I might want only href.

Connected to this topic, once the definition of custom Links becomes available, I'd like to have the ability to provide example for them. Currently, the only way (that I'm aware of) to do so is the following:

@Entity
@Table(name = "customers")
@Schema(example = "{\"_links\": {\"self\": {\"href\": \"http://<domain:port>/customers\"}}}")
public class Customer extends RepresentationModel<Customer> {

The problem with this approach, that it is completely overrides additional properties and annotations of the RepresentationModel and that would I couldn't rely on the autogeneration of the properties and their Annotations, regarding OpenAPI examples.
image

Summary

  • Are there any way, to override the default Link schema?
  • Is it possible to define Link schema by RepresentationModel?
  • Is it possible to define my own examples for these Links?

My ultimate goal is to provide a straighforward API documentation to my API consumers which in this context means, Swagger UI won't suggest properties of a given Schema that may never be received.

build.gradle
plugins {
  id 'java'
  id 'org.springframework.boot' version '3.1.5'
  id 'io.spring.dependency-management' version '1.1.3'
  id 'org.asciidoctor.jvm.convert' version '3.3.2'
}

group = 'hu.roncsak'
version = '0.0.1-SNAPSHOT'

java {
  sourceCompatibility = '17'
}

repositories {
  mavenCentral()
}

ext {
  set('snippetsDir', file("build/generated-snippets"))
  h2Version = '2.1.214'
  springBootStarterVersion = '3.1.5'
  springOpenApiStarterVersion = '2.2.0'
  springRestDocsMockMvcVersion = '3.0.0'
  springSecurityVersion = '6.1.5'
}

dependencies {
  implementation "org.springframework.boot:spring-boot-starter-data-jpa:$springBootStarterVersion"
  implementation "org.springframework.boot:spring-boot-starter-data-rest:$springBootStarterVersion"
  implementation "org.springframework.boot:spring-boot-starter-hateoas:$springBootStarterVersion"
  implementation "org.springframework.boot:spring-boot-starter-oauth2-authorization-server:$springBootStarterVersion"
  implementation "org.springframework.boot:spring-boot-starter-oauth2-client:$springBootStarterVersion"
  implementation "org.springframework.boot:spring-boot-starter-security:$springBootStarterVersion"
  implementation "org.springframework.boot:spring-boot-starter-web:$springBootStarterVersion"
  implementation "org.springdoc:springdoc-openapi-starter-common:$springOpenApiStarterVersion"
  implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:$springOpenApiStarterVersion"
  developmentOnly "org.springframework.boot:spring-boot-devtools:$springBootStarterVersion"
  runtimeOnly "com.h2database:h2:$h2Version"
  testImplementation "org.springframework.boot:spring-boot-starter-test:$springBootStarterVersion"
  testImplementation "org.springframework.restdocs:spring-restdocs-mockmvc:$springRestDocsMockMvcVersion"
  testImplementation "org.springframework.security:spring-security-test:$springSecurityVersion"
}

tasks.named('test') {
  outputs.dir snippetsDir
  useJUnitPlatform()
}

tasks.named('asciidoctor') {
  inputs.dir snippetsDir
  dependsOn test
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions