10
votes

I am building a JSON for a REST web service. The schema however has grown to over 1300 lines and I want to split it up across multiple files. I am unit testing my schema against a folder of JSON sample responses using json-schema-validator version 2.1.8.

I know you have import types defined in your current file like { "$ref": "#/definitions/MyBool" }, however if I wanted to move the definition of MyBool to another file, like Common.schema.json, how would I reference it then?

I tried { "$ref": "Common.schema.json/definitions/MyBoolean" }, { "$ref": "./Common.schema.json/defintion/MyBoolean" }, and { "$ref": "file://./Common.schema.json/definitions/MyBoolean" } but none of them work.

The answer on "Does JSON Schema validation in common-js utils support references?" seems like it should work but I can't seem to get the syntax right.

I'm loading the schema with:

JsonNode mySchema = JsonLoader.fromReader(   new InputStreamReader(  JsonSchemaTest.class.getResourceAsStream( "/json/schema/MySchema.schema.json" )  )   );

and then validating it with:

JsonSchemaFactory.byDefault().getValidator().validate(   schema,   new InputStreamReader(  getClass().getResourceAsStream( "/json/sample/MyJsonSample.json" )  )   ).isSuccess();

FWIW MyBool looks like:

"MyBool": {
    "type": "object",
    "properties": {
        "value" :{
            "type": "string",
            "enum": [ "true", "false", "file not found" ]
        }
    },
    "required": ["value"],
    "additionalProperties": false
}

When I don't try to extract MyBool, the schema validates all my JSON samples correctly.


The exception I receive is:

com.github.fge.jsonschema.core.exceptions.ProcessingException: fatal: unable to dereference URI "file:/Common.schema.json/definitions/MyBool#"
    level: "fatal"
    uri: "file:/Common.schema.json/definitions/MyBool#"
    exceptionMessage: "\\Common.schema.json\\definitions\\MyBool (The system cannot find the path specified)"

    at com.github.fge.jsonschema.core.load.URIManager.getContent(URIManager.java:108)
    at com.github.fge.jsonschema.core.load.SchemaLoader$1.load(SchemaLoader.java:108)
    at com.github.fge.jsonschema.core.load.SchemaLoader$1.load(SchemaLoader.java:103)
    at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3524)
    at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2317)
    at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2280)
    at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2195)
    at com.google.common.cache.LocalCache.get(LocalCache.java:3934)
    at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3938)
    at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4821)
    at com.github.fge.jsonschema.core.load.SchemaLoader.get(SchemaLoader.java:165)
    at com.github.fge.jsonschema.core.load.RefResolver.rawProcess(RefResolver.java:113)
    at com.github.fge.jsonschema.core.load.RefResolver.rawProcess(RefResolver.java:50)
    at com.github.fge.jsonschema.core.processing.RawProcessor.process(RawProcessor.java:76)
    at com.github.fge.jsonschema.core.processing.RawProcessor.process(RawProcessor.java:40)
    at com.github.fge.jsonschema.core.processing.ProcessorChain$ProcessorMerger.process(ProcessorChain.java:188)
    at com.github.fge.jsonschema.core.processing.ProcessingResult.of(ProcessingResult.java:78)
    at com.github.fge.jsonschema.core.processing.CachingProcessor$1.load(CachingProcessor.java:127)
    at com.github.fge.jsonschema.core.processing.CachingProcessor$1.load(CachingProcessor.java:119)
    at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3524)
    at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2317)
    at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2280)
    at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2195)
    at com.google.common.cache.LocalCache.get(LocalCache.java:3934)
    at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3938)
    at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4821)
    at com.github.fge.jsonschema.core.processing.CachingProcessor.process(CachingProcessor.java:108)
    at com.github.fge.jsonschema.processors.validation.ValidationChain.process(ValidationChain.java:106)
    at com.github.fge.jsonschema.processors.validation.ValidationChain.process(ValidationChain.java:55)
    at com.github.fge.jsonschema.core.processing.ProcessorMap$Mapper.process(ProcessorMap.java:165)
    at com.github.fge.jsonschema.core.processing.ProcessingResult.of(ProcessingResult.java:78)
    at com.github.fge.jsonschema.core.processing.CachingProcessor$1.load(CachingProcessor.java:127)
    at com.github.fge.jsonschema.core.processing.CachingProcessor$1.load(CachingProcessor.java:119)
    at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3524)
    at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2317)
    at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2280)
    at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2195)
    at com.google.common.cache.LocalCache.get(LocalCache.java:3934)
    at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3938)
    at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4821)
    at com.github.fge.jsonschema.core.processing.CachingProcessor.process(CachingProcessor.java:108)
    at com.github.fge.jsonschema.processors.validation.ValidationProcessor.process(ValidationProcessor.java:83)
    at com.github.fge.jsonschema.processors.validation.ValidationProcessor.processObject(ValidationProcessor.java:179)
    at com.github.fge.jsonschema.processors.validation.ValidationProcessor.process(ValidationProcessor.java:121)
    at com.github.fge.jsonschema.processors.validation.ValidationProcessor.processArray(ValidationProcessor.java:149)
    at com.github.fge.jsonschema.processors.validation.ValidationProcessor.process(ValidationProcessor.java:119)
    at com.github.fge.jsonschema.processors.validation.ValidationProcessor.processObject(ValidationProcessor.java:179)
    at com.github.fge.jsonschema.processors.validation.ValidationProcessor.process(ValidationProcessor.java:121)
    at com.github.fge.jsonschema.processors.validation.ValidationProcessor.process(ValidationProcessor.java:48)
    at com.github.fge.jsonschema.keyword.validator.draftv4.OneOfValidator.validate(OneOfValidator.java:67)
    at com.github.fge.jsonschema.processors.validation.ValidationProcessor.process(ValidationProcessor.java:100)
    at com.github.fge.jsonschema.processors.validation.ValidationProcessor.process(ValidationProcessor.java:48)
    at com.github.fge.jsonschema.core.processing.ProcessingResult.of(ProcessingResult.java:78)
    at com.github.fge.jsonschema.main.JsonValidator.validate(JsonValidator.java:103)
    at com.github.fge.jsonschema.main.JsonValidator.validate(JsonValidator.java:123)
    at com.initech.ws.json.BaseJsonSchemaTest.jsonFileShouldValidate(BaseJsonSchemaTest.java:84)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.junit.runners.Suite.runChild(Suite.java:127)
    at org.junit.runners.Suite.runChild(Suite.java:26)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.junit.runners.Suite.runChild(Suite.java:127)
    at org.junit.runners.Suite.runChild(Suite.java:26)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:211)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
3
Hello! Can you show the code you use to load your schema? Also, which version are you using?fge
@fge I've updated the question with those details, but I have not yet had a chance to try your suggestion.Sled
Does relative paths mean you get to use things like ..?CMCDragonkai
@CMCDragonkai yesSled

3 Answers

18
votes

What you need there is being able to reference your files using an absolute URI.

Supposing you are using the stable version (ie 2.0.2), load your schema using this method.

Given where your file is located, use:

final JsonSchema schema 
    = factory.getJsonSchema("resource:/json/schema/MySchema.schema.json");

This means URI resolution in this schema will be made relatively to this (loading) URI; so, refering to your MyBoolean.json, you will do:

{
    "$ref": "MyBoolean.json#/pointer/into/file"
}

If it is located at, for instance, /json/schema/subschemas then you will write:

{
    "$ref": "subschemas/MyBoolean.json#/pointer/into/file"
}

Parents also work etc.


Note that as noted in the README, 2.1.x is a development version! I am currently reworking the API...

3
votes

The following solution worked for me. The path is relative to location where I run mvn goals.

"items": {
                "type": "object",
                "$ref": "file:src/xyz/abc/lmn/DeviceRecord.json"
         }

Here file: is the path from where you are executing the maven goal.

0
votes

Old question but I was able to get this working by doing

given().when().get("...")
                .then()
                .statusCode(200)
                .body(matchesJsonSchemaInClasspath("schemas/the-array-schema.json"));

Then in the-array-schema.json (in the /resources/schemas directory), I have

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "array",
  "items": {
    "$ref": "the-object-schema.json"
  }
}

where the-object-schema.json is also in the /resources/schemas directory.