Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can I access definitions in schema-store using $ref? #2420

Closed
imjuni opened this issue Apr 28, 2024 · 1 comment
Closed

How can I access definitions in schema-store using $ref? #2420

imjuni opened this issue Apr 28, 2024 · 1 comment

Comments

@imjuni
Copy link

imjuni commented Apr 28, 2024

Motivation

When developing a RESTful server using Express.js, Fastify.js, etc. in a Node environment, it uses json-schema to validate API request inputs. If you're using json-schema to validate request inputs, integrating multiple schemas can be more manageable as the number of APIs grows.

interface IPeople {
  firstName: string;
  lastName: string;
}

interface IStudent extends IPeople {
  major: string;
}

interface IProfessor extends IPeople {
  room: number;
}

The example above is in typescript, but it can also be expressed in json-schema.

{
  "$id": "IPeople",
  "properties": {
    "firstName": {
      "type": "string"
    },
    "lastName": {
      "type": "string"
    }
  },
}
{
  "$id": "IStudent",
  "properties": {
    "major": {
      "type": "string"
    },
    "$ref": "IPeople"
  },
}
{
  "$id": "IProfessor",
  "properties": {
    "room": {
      "type": "number"
    },
    "$ref": "IPeople"
  },
}

It's useful to have a structured schema like this.

Problem

I'm looking for an way to configure a schema registry per API in one json-schema store. For example, I'm looking for a way to access the contents inside definitions in two schema stores, https://json.schemastore.org/eslintrc.json and https://json.schemastore.org/partial-eslint-plugins.json.

import Ajv from 'ajv';

const ajv = new Ajv();

const [reply01, reply02] = await Promise.all([
  fetch('https://json.schemastore.org/eslintrc.json', { method: 'GET' }),
  fetch('https://json.schemastore.org/partial-eslint-plugins.json', {
    method: 'GET',
  }),
]);

const [resp01, resp02] = await Promise.all([reply01.json(), reply02.json()]);

ajv.addSchema(resp02);
ajv.addSchema(resp01);

const refs = [
  'https://json.schemastore.org/eslintrc.json/definitions/stringOrStringArray',
  'https://json.schemastore.org/eslintrc.json/#/definitions/stringOrStringArray',
  'https://json.schemastore.org/eslintrc.json#/definitions/stringOrStringArray',
  '#/definitions/stringOrStringArray',
  'https://json.schemastore.org/partial-eslint-plugins.json/definitions/ruleNumber',  
  'https://json.schemastore.org/partial-eslint-plugins.json#/definitions/ruleNumber',  
  'https://json.schemastore.org/partial-eslint-plugins.json/ruleNumber',  
]

const validators = refs.map((ref) => {
  try {
    const validator = ajv.compile({ $ref: ref, });
    return validator
  } catch (error) {
    console.log(error);
    return undefined;
  }
});

Expectation

How do I access the above eslintrc.json/definitions?

Environments

  1. Node v20.11.1
  2. AJV 8.12.0
  3. Reproducable Repo.
    1. https://github.com/imjuni/json-schema-ref-test.git
@jasoniangreen
Copy link
Collaborator

Hi @imjuni, after digging into the error messages when trying to load the refs (or actually I tested using ajv.getSchema as it was simpler) I found that the original schemas were not loading correctly because of missing formats that are being used in those schemas.

I fixed this by adding ajv-formats to the example.

import Ajv from 'ajv';
import addFormats from "ajv-formats";

const ajv = new Ajv();
addFormats(ajv);

From here you can see which of your ref syntax works properly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

2 participants