APIDevTools / json-schema-ref-parser

Parse, Resolve, and Dereference JSON Schema $ref pointers in Node and browsers
https://apitools.dev/json-schema-ref-parser
MIT License
953 stars 227 forks source link

Repeating relative $refs with id's result in invalid json schema generation #355

Open phawxby opened 1 month ago

phawxby commented 1 month ago

Sample https://github.com/phawxby/json-ref-example/blob/main/src/example.ts

What I think is happening here is that the repetition of the reference to root.schema.json is being resolved down to $refs in later references. However because those sub schemas (sub1.schema.json) include as $id that changes the base uri for resolution. The result is #/oneOf/0/allOf/0 is being resolved from sub2.schema.json and not from root.schema.json.

When passed into AJV this then results in.

MissingRefError: can't resolve reference #/oneOf/0/allOf/0 from id sub2.schema.json

Removing the $id from sub*.schema.json which prevents the base uri from being changed corrects the issue.

Compiled output

{
  '$id': 'root.schema.json',
  '$schema': 'https://json-schema.org/draft/2019-09/schema',
  type: 'object',
  oneOf: [
    {
      '$id': 'sub1.schema.json',
      '$schema': 'https://json-schema.org/draft/2019-09/schema',
      type: 'object',
      allOf: [
        {
          '$id': 'base.schema.json',
          '$schema': 'https://json-schema.org/draft/2019-09/schema',
          type: 'object',
          properties: { foo: { type: 'string' } }
        },
        { properties: { name: { type: 'string', const: 'sub1' } } }
      ]
    },
    {
      '$id': 'sub2.schema.json',
      '$schema': 'https://json-schema.org/draft/2019-09/schema',
      type: 'object',
      allOf: [
        { '$ref': '#/oneOf/0/allOf/0' },
        { properties: { name: { type: 'string', const: 'sub2' } } }
      ]
    },
    {
      '$id': 'sub3.schema.json',
      '$schema': 'https://json-schema.org/draft/2019-09/schema',
      type: 'object',
      allOf: [
        { '$ref': '#/oneOf/0/allOf/0' },
        { properties: { name: { type: 'string', const: 'sub3' } } }
      ]
    }
  ]
}