ajv-validator / ajv

The fastest JSON schema Validator. Supports JSON Schema draft-04/06/07/2019-09/2020-12 and JSON Type Definition (RFC8927)
https://ajv.js.org
MIT License
13.47k stars 864 forks source link

Ref within def does not act consistently #2391

Closed meghprkh closed 1 week ago

meghprkh commented 2 months ago

What version of Ajv are you using? Does the issue happen if you use the latest version? Yes

├── ajv-cli@5.0.0
├── ajv@8.12.0

Ajv options object

CLI invocation ajv validate -s test.schema.json -d test.json

JSON Schema

This schema would work complain that:

schema schema/test.schema.json is invalid
error: can't resolve reference #/$defs/JSONValue from id KVMap
{
  "$ref": "#/$defs/KVMap",
  "$defs": {
    "JSONValue": {
      "$id": "JSONValue"
    },
    "KVMap": {
      "$id": "KVMap",
      "type": "object",
      "patternProperties": {
        "^(.*)$": {
          "$ref": "#/$defs/JSONValue"
        }
      }
    }
  }
}

I am unsure if refs should use IDs instead of JSON Pointers everywhere, but IDs do seem to work.

The inconsistency between VSCode and ajv's validator wrt IDs is that ajv accepts ID as JSONValue instead of #JSONValue too, whereas VSCode does not. I cant find any mention of this on JSONSchema and think it might be VSCode which is wrong here.

Sample data

{}

What results did you expect?

This should be a valid case in JSON schema, because dictionaries are not sorted so it would be impossible to refer to a non-id anchor based def.

Are you going to resolve the issue? I dont know

jasoniangreen commented 2 weeks ago

I think the problem is you are using both $id in the wrong way. $id is a way to refer to a schema or subschema but I've not seen it used in $defs before since they already have a syntax to refer to them. The $id is most commonly used to define the base for all your $refs. So basically your example works if you just remove these extra $id props.

{
  "$ref": "#/$defs/KVMap",
  "$defs": {
    "JSONValue": {
    },
    "KVMap": {
      "type": "object",
      "patternProperties": {
        "^(.*)$": {
          "$ref": "#/$defs/JSONValue"
        }
      }
    }
  }
}