Skip to content

Support for internal refs when generating JSON schemas #2894

@aringeri

Description

@aringeri

Description

Hi,
My overall goal is to use hey-api/openapi-ts in combination react-jsonschema-form.

I would like to generate react forms from component schemas found in an OpenAPI spec:

OpenAPI.json ->  JSON Schema (@hey-api/schemas) -> React Form (react-jsonschema-form)

While this works well for simple components, I find it falls down when a component schema references another component in the same OpenAPI spec.

For example this OpenAPI spec, the January definition has a $ref to Answer (example taken from this repo):

openapi: 3.0.3
info:
  title: title
  description: description
  version: 1.0.0
components:
  schemas:
    January:
      description: January description
      type: object
      required:
        - isJanuary
      properties:
        isJanuary:
          description: isJanuary description
          $ref: '#/components/schemas/Answer'
        isFebruary:
          description: isFebruary description
          $ref: '#/components/schemas/Answer'
    Answer:
      type: string
      nullable: true
      enum:
        - yes
        - no

hey-api/openapi-ts generates the following schemas.gen.ts file:

// This file is auto-generated by @hey-api/openapi-ts

export const Answer = {
  type: "string",
  nullable: true,
  enum: ["yes", "no"],
} as const;


export const January = {
  description: "January description",
  type: "object",
  required: ["isJanuary"],
  properties: {
    isJanuary: {
      description: "isJanuary description",
      $ref: "#/components/schemas/Answer",
    },
    isFebruary: {
      description: "isFebruary description",
      $ref: "#/components/schemas/Answer",
    },
  },
} as const;

If I try to pass the January schema to a react-jsonschema-form Form, it fails because it cannot find the reference "#/components/schemas/Answer":

import Form from '@rjsf/core';
import validator from '@rjsf/validator-ajv8';
import { January } from "@/schemas.gen.ts";

...

// Fails with 'Could not find a definition for #/components/schemas/Answer.'
<Form
   schema={January}
   validator={validator}
/>

A current workaround is to attach the referenced types in the schema given to the form, but this is not scalable for larger/complex schemas.
(We would hopefully not have to manually do this for each schema)

const schema = {
    components: {
       schemas: {
         Answer: Answer
       }
    },
    ...January
}

Can you suggest any ways forward?
I would essentially want each JSON schema to be self-contained and pull in any required references.

Potentially references could be resolved in the generated typescript (assuming no self/circular references):

export const Answer = {
  type: "string",
  nullable: true,
  enum: ["yes", "no"],
} as const;


export const January = {
  description: "January description",
  type: "object",
  required: ["isJanuary"],
  properties: {
    isJanuary: {
      description: "isJanuary description",
      ...Answer
    },
    isFebruary: {
      description: "isFebruary description",
      ...Answer
    },
  },
} as const;

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions