everit-org/json-schema

IDs are always validated as URIs.

Opened this issue · 2 comments

Description
From what I understand, the 'id' keyword at the root level is used as a URI reference, but only at this point (I might be wrong). However, I see that Everit performs a recursive search in the child elements, looking for all the IDs, and these are also validated as URIs.

In the following example, I understand that the ID should not be considered as a URI:

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "$ref": "#/definitions/SubstitutionRules",
  "definitions": {
    "SubstitutionRules": {
      "x-amf-examples": {
        "output": {
          "substitutionRules": [
            {
              "id": "ABCDEGH@20201005000000 @20201031000000 @S",
              "user": "ABCDEGH",
              "beginDate": "2020-10-17T00:00:00Z",
              "endDate": "2020-10-27T00:00:00Z",
              "fullName": "Abcde Abcde",
              "isEnabled": 1,
              "supportsDeleteSubstitutionRule": true,
              "supportsEnableSubstitutionRule": true,
              "mode": 1,
              "profile": "ZPROCUREMENT",
              "profileText": "Procurement",
              "sourceSystem": "ENUM1"
            }
          ]
        }
      },
      "type": "object",
      "additionalProperties": true,
      "required": [
        "substitutionRules"
      ],
      "properties": {
        "substitutionRules": {
          "items": {
            "$ref": "#/definitions/type"
          },
          "type": "array"
        }
      }
    },
    "type": {
      "type": "object",
      "additionalProperties": true,
      "required": [
        "beginDate",
        "endDate"
      ],
      "properties": {
        "id": {
          "type": "string"
        },
        "user": {
          "type": "string"
        },
        "beginDate": {
          "type": "string",
          "format": "date-time"
        },
        "endDate": {
          "type": "string",
          "format": "date-time"
        },
        "fullName": {
          "type": "string"
        },
        "isEnabled": {
          "description": "Mapped to Permission Scope on the Exp layer takes value 1 (Receive My Tasks) or 2 (Fill In For Me)",
          "type": "integer"
        },
        "supportsDeleteSubstitutionRule": {
          "type": "boolean"
        },
        "supportsEnableSubstitutionRule": {
          "type": "boolean"
        },
        "mode": {
          "description": "Mapped to Delegation Type on the Exp layer takes value 0 (Unplanned) or 1 (Planned)",
          "type": "integer"
        },
        "role": {
          "description": "Mapped to Role on the Exp Layer takes values 1 (Approve), 2(Approve&Update), 3(Reporting), 4(Update)",
          "type": "integer"
        },
        "profile": {
          "description": "Used for Invoice system as an static value \"ZPROCUREMENT\"",
          "type": "string"
        },
        "profileText": {
          "description": "Used for Invoice system as an static value \"Procurement\"",
          "type": "string"
        },
        "sourceSystem": {
          "$ref": "#/definitions/type_1"
        }
      }
    },
    "type_1": {
      "type": "string",
      "description": "The source system of the data in SAP",
      "enum": [
        "ENUM1",
        "ENUM2",
        "ENUM3"
      ]
    }
  }
}

I tested with some online validators and everything seems to work fine, but Everit shows the following error:

_
java.lang.RuntimeException: java.net.URISyntaxException: Illegal character in path at index 22: ABCDEGH@20201005000000 @20201031000000 @s

at org.everit.json.schema.loader.internal.ReferenceResolver.resolve(ReferenceResolver.java:29)
at org.everit.json.schema.loader.LoadingState.extractChildId(LoadingState.java:32)
at org.everit.json.schema.loader.LoadingState.<init>(LoadingState.java:72)
at org.everit.json.schema.loader.LoadingState.childFor(LoadingState.java:120)
at org.everit.json.schema.loader.LoadingState.childFor(LoadingState.java:127)
at org.everit.json.schema.loader.JsonArray.at(JsonArray.java:29)
at org.everit.json.schema.loader.SubschemaRegistry.collectObjectsWithId(SubschemaRegistry.java:29)
at org.everit.json.schema.loader.SubschemaRegistry.collectObjectsWithId(SubschemaRegistry.java:24)
at org.everit.json.schema.loader.SubschemaRegistry.collectObjectsWithId(SubschemaRegistry.java:24)
at org.everit.json.schema.loader.SubschemaRegistry.collectObjectsWithId(SubschemaRegistry.java:24)
at org.everit.json.schema.loader.SubschemaRegistry.collectObjectsWithId(SubschemaRegistry.java:24)
at org.everit.json.schema.loader.SubschemaRegistry.collectObjectsWithId(SubschemaRegistry.java:24)
at org.everit.json.schema.loader.SubschemaRegistry.<init>(SubschemaRegistry.java:12)
at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1220)
at org.everit.json.schema.loader.LoadingState.getSubschemaRegistry(LoadingState.java:169)
at org.everit.json.schema.loader.ReferenceLookup.lookupObjById(ReferenceLookup.java:71)
at org.everit.json.schema.loader.ReferenceLookup.lookup(ReferenceLookup.java:138)
at org.everit.json.schema.loader.ReferenceSchemaExtractor.extract(SchemaExtractor.java:199)
at org.everit.json.schema.loader.AbstractSchemaExtractor.extract(SchemaExtractor.java:114)
at org.everit.json.schema.loader.SchemaLoader.runSchemaExtractors(SchemaLoader.java:411)
at org.everit.json.schema.loader.SchemaLoader.loadSchemaObject(SchemaLoader.java:388)
at org.everit.json.schema.loader.JsonValue$Multiplexer.requireAny(JsonValue.java:47)
at org.everit.json.schema.loader.SchemaLoader.load(SchemaLoader.java:462)
at org.example.JsonSchemaTest.dereferencing(Main.java:30)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:147)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:127)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:90)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:55)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:102)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57)
at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)

Caused by: java.net.URISyntaxException: Illegal character in path at index 22: ABCDEGH@20201005000000 @20201031000000 @s
at java.base/java.net.URI$Parser.fail(URI.java:2974)
at java.base/java.net.URI$Parser.checkChars(URI.java:3145)
at java.base/java.net.URI$Parser.parseHierarchical(URI.java:3227)
at java.base/java.net.URI$Parser.parse(URI.java:3186)
at java.base/java.net.URI.(URI.java:623)
at org.everit.json.schema.loader.internal.ReferenceResolver.resolve(ReferenceResolver.java:26)
... 93 more_

I have attached a simplified application to reproduce the issue mentioned.

t-json-schema-m.zip

erosb commented

Hi @erosb thanks for your response.

I'm taking the definition from https://json-schema.org/understanding-json-schema/structuring#id, and in my case, I need to use draft 4.

image

From what I see in SubschemaRegistry, it recursively searches throughout the entire JSON schema for any references to id and is validated as an URI.