hyperjump-io / json-schema

JSON Schema Validation, Annotation, and Bundling. Supports Draft 04, 06, 07, 2019-09, 2020-12, OpenAPI 3.0, and OpenAPI 3.1
https://json-schema.hyperjump.io/
MIT License
216 stars 22 forks source link

Annotations fail to properly decode pointers #54

Closed hudlow closed 6 months ago

hudlow commented 6 months ago

The following code produces an error:

import { registerSchema } from "@hyperjump/json-schema/draft-2020-12";
import { annotate } from "@hyperjump/json-schema/annotations/experimental";

const schemaId = "https://fabc10a6-e699-415c-b5e2-25702695a939.example.hudlow.org";

const schema = {
  $schema: "https://json-schema.org/draft/2020-12/schema",
  $id: schemaId,
  properties: {
    paths: {
      properties: {
        "/pets/{id}": {
          title: "path",
          properties: {
            get: {}
          }
        }
      }
    }
  }
};

registerSchema(schema);

const instance = await annotate(schemaId, {
  paths: {
    "/pets/{id}": {
      get: {}
    }
  }
});
json-schema-sandbox $ node ./test-draft-2020-12.js
file:///Volumes/Projects/github.com/hyperjump-io/json-schema/node_modules/@hyperjump/json-pointer/lib/index.js:149
    throw TypeError(`Value at '${cursor}' is undefined and does not have property '${segment}'`);
          ^

TypeError: Value at '/paths/~1pets~1%7Bid%7D' is undefined and does not have property 'get'
    at applySegment (file:///Volumes/Projects/github.com/hyperjump-io/json-schema/node_modules/@hyperjump/json-pointer/lib/index.js:149:11)
    at _get (file:///Volumes/Projects/github.com/hyperjump-io/json-schema/node_modules/@hyperjump/json-pointer/lib/index.js:45:30)
    at _get (file:///Volumes/Projects/github.com/hyperjump-io/json-schema/node_modules/@hyperjump/json-pointer/lib/index.js:45:12)
    at _get (file:///Volumes/Projects/github.com/hyperjump-io/json-schema/node_modules/@hyperjump/json-pointer/lib/index.js:45:12)
    at fn (file:///Volumes/Projects/github.com/hyperjump-io/json-schema/node_modules/@hyperjump/json-pointer/lib/index.js:36:27)
    at get (file:///Volumes/Projects/github.com/hyperjump-io/json-schema/node_modules/@hyperjump/json-pointer/lib/index.js:37:39)
    at Module.get (file:///Volumes/Projects/github.com/hyperjump-io/json-schema/lib/instance.js:24:12)
    at Object.<anonymous> (file:///Volumes/Projects/github.com/hyperjump-io/json-schema/annotations/index.js:41:28)
    at publish (file:///Volumes/Projects/github.com/hyperjump-io/json-schema/lib/pubsub.js:23:57)
    at Object.interpret (file:///Volumes/Projects/github.com/hyperjump-io/json-schema/lib/keywords/validation.js:66:13)

Node.js v18.17.1

The reason is that the JSON pointers for the instance location of an annotation are not properly URI-decoded. Consider the the above schema will produce this annotations value:

{
  "/paths/~1pets~1%7Bid%7D": { "https://json-schema.org/keyword/title": [ "path" ] }
}

But this is wrong — because this annotations object is not keyed by a relative pointer URI, but rather by the fragment value from a relative pointer URI, it should be:

{
  "/paths/~1pets~1{id}": { "https://json-schema.org/keyword/title": [ "path" ] }
}

This mismatched logic produces the error, but the annotations are actually themselves wrong.