From cdd33d071d357d0d2dcf1c9b0c0e5cc58ad2a1d7 Mon Sep 17 00:00:00 2001 From: Johan Dorland Date: Wed, 5 Dec 2018 17:13:54 +0100 Subject: [PATCH] Update documentation and add draft crossreference test --- README.md | 41 ++++++++++++++++++++++++++++++++++++++--- schemaLoader_test.go | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 242e0d3..24ca347 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,6 @@ func main() { fmt.Printf("- %s\n", desc) } } - } @@ -149,6 +148,7 @@ To check the result : } ``` + ## Loading local schemas By default `file` and `http(s)` references to external schemas are loaded automatically via the file system or via http(s). An external schema can also be loaded using a `SchemaLoader`. @@ -189,10 +189,45 @@ It's also possible to pass a `ReferenceLoader` to the `Compile` function that re ```go err = sl.AddSchemas(loader3) -schema,err := sl.Compile(NewReferenceLoader("http://some_host.com/main.json")) +schema, err := sl.Compile(gojsonschema.NewReferenceLoader("http://some_host.com/main.json")) +``` + +Schemas added by `AddSchema` and `AddSchemas` are only validated when the entire schema is compiled, unless meta-schema validation is used. + +## Using a specific draft +By default `gojsonschema` will try to detect the draft of a schema by using the `$schema` keyword and parse it in a strict draft-04, draft-06 or draft-07 mode. If `$schema` is missing, or the draft version is not explicitely set, a hybrid mode is used which merges together functionality of all drafts into one mode. + +Autodectection can be turned off with the `AutoDetect` property. Specific draft versions can be specified with the `Draft` property. + +```go +sl := gojsonschema.NewSchemaLoader() +sl.Draft = gojsonschema.Draft7 +sl.AutoDetect = false +``` + +If autodetection is on (default), a draft-07 schema can savely reference draft-04 schemas and vice-versa, as long as `$schema` is specified in all schemas. + +## Meta-schema validation +Schemas that are added using the `AddSchema`, `AddSchemas` and `Compile` can be validated against their meta-schema by setting the `Validate` property. + +The following example will produce an error as `multipleOf` must be a number. If `Validate` is off (default), this error is only returned at the `Compile` step. + +```go +sl := gojsonschema.NewSchemaLoader() +sl.Validate = true +err := sl.AddSchemas(gojsonschema.NewStringLoader(`{ + $id" : "http://some_host.com/invalid.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "multipleOf" : true +}`)) + ``` ``` + ``` + +Errors returned by meta-schema validation are more readable and contain more information, which helps significantly if you are developing a schema. + +Meta-schema validation also works with a custom `$schema`. In case `$schema` is missing, or `AutoDetect` is set to `false`, the meta-schema of the used draft is used. -Schemas added by `AddSchema` and `AddSchemas` are only validated when the entire schema is compiled. Returned errors only contain errors about invalid URIs or if a URI is associated with multiple schemas. This may change in the future. ## Working with Errors diff --git a/schemaLoader_test.go b/schemaLoader_test.go index 5808038..8a2e9ed 100644 --- a/schemaLoader_test.go +++ b/schemaLoader_test.go @@ -123,3 +123,40 @@ func TestSchemaDetection(t *testing.T) { _, err = sl.Compile(loader) assert.Nil(t, err) } + +func TestDraftCrossReferencing(t *testing.T) { + + // Tests the following cross referencing with any combination + // of autodetection and preset draft version. + + loader1 := NewStringLoader(`{ + "$schema" : "http://json-schema.org/draft-04/schema#", + "id" : "http://localhost:1234/file.json", + "$id" : "http://localhost:1234/file.json", + "exclusiveMinimum" : 5 + }`) + loader2 := NewStringLoader(`{ + "$schema" : "http://json-schema.org/draft-07/schema#", + "id" : "http://localhost:1234/main.json", + "$id" : "http://localhost:1234/main.json", + "$ref" : "file.json" + }`) + + for _, b := range []bool{true, false} { + for _, draft := range []Draft{Draft4, Draft6, Draft7} { + sl := NewSchemaLoader() + sl.Draft = draft + sl.AutoDetect = b + + err := sl.AddSchemas(loader1) + assert.Nil(t, err) + _, err = sl.Compile(loader2) + + // It will always fail with autodetection on as "exclusiveMinimum" : 5 + // is only valid since draft-06. With autodetection off it will pass if + // draft-06 or newer is used + + assert.Equal(t, err == nil, !b && draft >= Draft6) + } + } +}