ajv-keywords icon indicating copy to clipboard operation
ajv-keywords copied to clipboard

Containing $ref in select statement throws error unless fully qualified.

Open sirockin opened this issue 7 years ago • 9 comments

Example code below throws the following error when it attempts to compile selectSchema2:

/Users/sirockin/source/f2/f2-schema/node_modules/ajv/lib/dotjs/ref.js:61
        throw new it.MissingRefError(it.baseId, $schema, $message);
        ^
Error: can't resolve reference defs.json#/definitions/int from id #

Example code:

var Ajv = require('ajv');

var schema = {
  "$id": "http://example.com/schemas/schema.json",
  "type": "object",
  "properties": {
    "foo": { "$ref": "defs.json#/definitions/int" },
    "bar": { "$ref": "defs.json#/definitions/str" }
  }
};

var selectSchema1={
  "$id": "http://example.com/schemas/select1.json",
  type: "object",
  required: ['kind'],
  properties: {
    kind: { type: 'string' }
  },
  select: { $data: '0/kind' },
  selectCases: {
    foo: {
      required: ['foo'],
      properties: {
        kind: {},
        foo: { type: 'string' }
      },
      additionalProperties: false
    },
    bar: {
      required: ['bar'],
      properties: {
        kind: {},
        bar: { type: 'number' }
      },
      additionalProperties: false
    }
  },
  selectDefault: {
    propertyNames: {
      not: { enum: ['foo', 'bar'] }
    }
  }
};

var selectSchema2={
  "$id": "http://example.com/schemas/select2.json",
  type: "object",
  required: ['kind'],
  properties: {
    kind: { type: 'string' }
  },
  select: { $data: '0/kind' },
  selectCases: {
    foo: {
      required: ['foo'],
      properties: {
        kind: {},
        foo: { "$ref": "defs.json#/definitions/int" }
      },
      additionalProperties: false
    },
    bar: {
      required: ['bar'],
      properties: {
        kind: {},
        bar: { type: 'number' }
      },
      additionalProperties: false
    }
  },
  selectDefault: {
    propertyNames: {
      not: { enum: ['foo', 'bar'] }
    }
  }
};


var defsSchema = {
  "$id": "http://example.com/schemas/defs.json",
  "definitions": {
    "int": { "type": "integer" },
    "str": { "type": "string" }
  }
};

// Validate against simple schema
var ajv = new Ajv({schemas: [schema, defsSchema]});
var validate = ajv.getSchema('http://example.com/schemas/schema.json');

var result = validate({ foo:2});
console.log("Simple schema validation result: " + result);

// Validate against select schema
ajv = new Ajv({schemas: [selectSchema1, defsSchema],$data:true});
require('ajv-keywords')(ajv, 'select');
validate = ajv.getSchema('http://example.com/schemas/select1.json');

var result = validate({ kind: 'foo', foo:"blah" });
console.log("Select schema validation result: " + result);

// Validate against select schema with refs - throws an error
ajv = new Ajv({schemas: [selectSchema2, defsSchema],$data:true});  
require('ajv-keywords')(ajv,'select');
validate = ajv.getSchema('http://example.com/schemas/select2.json'); // Error thrown here
var result = validate({ kind: 'foo', foo: 'any' });
console.log("Select with refs schema validation result: " + result);



sirockin avatar Oct 20 '17 11:10 sirockin

Did some further investigations: The reference will work but needs to be specified with the full ID ie http://example.com/schemas/defs.json#/definitions/int but not defs.json#/definitions/int. This applies even when using a ref declared in the same schema - so you can't for example use #/definitions/int to refer to a locally defined definition.

This is inconsistent with other rules for $ref usage so should at least be documented or preferably fixed.

sirockin avatar Oct 20 '17 14:10 sirockin

That's why it's BETA :)

Select indeed compiles cases as separate schemas without resolving the IDs in them against the current base.

Happy with PR marking it as a limitation in docs and with a fix, but I won't invest more time in this keyword until there are better chances of it being adopted by the spec - please express your support in the relevant issue in JSON Schema GitHub org.

epoberezkin avatar Oct 20 '17 15:10 epoberezkin

No problem. I'll support its adoption. Any chance you could update the docs to clarify?

On Fri, 20 Oct 2017, 17:14 Evgeny Poberezkin, [email protected] wrote:

That's why it's BETA :)

Select indeed compiles cases as separate schemas without resolving the IDs in them against the current base.

Happy with PR marking it as a limitation in docs and with a fix, but I won't invest more time in this keyword until there are better chances of it being adopted by the spec - please express your support in the relevant issue in JSON Schema GitHub org.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/epoberezkin/ajv-keywords/issues/42#issuecomment-338235992, or mute the thread https://github.com/notifications/unsubscribe-auth/AHaqBY-MUr6DbA3IBKvgMNCBJ52Ax5YAks5suLjrgaJpZM4QAg-v .

sirockin avatar Oct 20 '17 15:10 sirockin

0/kind , what`s mean number zero??

coco-super avatar May 08 '19 10:05 coco-super

It’s relative JSON pointer spec - “0” means the current level in the data (I.e. 0 levels up). “1” would mean one level up etc.

epoberezkin avatar May 09 '19 04:05 epoberezkin

It’s relative JSON pointer spec - “0” means the current level in the data (I.e. 0 levels up). “1” would mean one level up etc.

what is the down one level ?

coco-super avatar May 09 '19 06:05 coco-super

image

coco-super avatar May 09 '19 08:05 coco-super

Why is my selectCase not working, is it wrong for me????????????? image

coco-super avatar May 09 '19 08:05 coco-super

image

coco-super avatar May 09 '19 08:05 coco-super