Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

About using jsonschema.CompileString #98

Closed
Zacama opened this issue Jan 3, 2023 · 6 comments
Closed

About using jsonschema.CompileString #98

Zacama opened this issue Jan 3, 2023 · 6 comments
Labels

Comments

@Zacama
Copy link

Zacama commented Jan 3, 2023

Hello, I have a question about using jsonschema: Why do I need to pass a URL parameter when calling CompileString?

@santhosh-tekuri
Copy link
Owner

the url you pass to CompileString gets used in error messages:

jsonschema.CompileString("schema.json", schemaString)
[I#] [S#] doesn't validate with file:///Users/santhosh/jsonschema/schema.json#
  [I#] [S#/$ref] doesn't validate with 'file:///Users/santhosh/jsonschema/t.json#/definitions/employee'
    [I#] [S#/definitions/employee/type] expected string, but got number

in above error message you can see file:///Users/santhosh/jsonschema/schema.json

also in detailed and verbose output formats, the absoluteKeywordLocation property uses this url

then you might ask, why can't we just internally use some default say schema.json and do not ask user. there is one reason why we are not assuming some default uri. see explanation below:

jsonschema.CompileString(`{
    "type": "object",
    "properties": {
        "p": { "$ref": "schema.json" }
    }
}`)

assume that we have schema.json in current working directory. and in above code the user intension is the $ref to load schema.json from current working directory. But if we assume default uri of passed schema string as schema.json then the $ref resolves the schema string itself, instead of schema.json from current working directory.

I hope I am able to explain why you need to pass URL parameter to CompileString

@Zacama
Copy link
Author

Zacama commented Jan 3, 2023

@santhosh-tekuri Thank you very much! I get it.

@Zacama Zacama closed this as completed Jan 3, 2023
@saward
Copy link

saward commented May 22, 2024

What happens when that URL is a valid URL? E.g., if I do this:

	sch, err := jsonschema.CompileString("http://json-schema.org/schema", sampleSchema)

Then my json sample seems to pass my schema validation when it should fail. But if I introduce a typo, .orrg instead of .org, it fails validation against the schema contained in sampleSchema, as I expect:

	sch, err := jsonschema.CompileString("http://json-schema.orrg/schema", sampleSchema)

I'm wondering if this string is just for local error reporting, what's happening here? (v5.3.1).

@santhosh-tekuri
Copy link
Owner

it is treated as if the schema is downloaded from that url. for example if you have "$ref" with same url, then your schema is used in that place

@saward
Copy link

saward commented May 23, 2024

$ref is not used in the document at all. Are you able to help me understand why the behaviour of the validation changes when we go from http://json-schema.org/schema to http://json-schema.orrg/schema? Where the second one works as expected, but the first does not.

Here's a minimal sample (https://go.dev/play/p/P7RqtVbTT_e), where schema2 fails as expected but schema1 passes:

package main

import (
	"encoding/json"
	"log"

	"github.com/santhosh-tekuri/jsonschema/v5"
)

var sampleSchema string = `{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "id": {
      "type": "integer"
    },
    "name": {
      "type": "string"
    }
  },
  "required": ["id", "name"]
}`

var sampleJSON string = `{
  "id": 456
}`

func main() {
	schema1, err := jsonschema.CompileString("http://json-schema.org/schema", sampleSchema)
	if err != nil {
		log.Fatalf("%#v", err)
	}

	schema2, err := jsonschema.CompileString("http://json-schema.orrg/schema", sampleSchema)
	if err != nil {
		log.Fatalf("%#v", err)
	}

	var v interface{}
	if err := json.Unmarshal([]byte(sampleJSON), &v); err != nil {
		log.Fatalf("%#v", err)
	}

	if err = schema1.Validate(v); err != nil {
		log.Printf("Failed validation against schema 1: %s\n", err)
	}

	if err = schema2.Validate(v); err != nil {
		log.Printf("Failed validation against schema 2: %s\n", err)
	}
}

Output:

2024/05/23 12:52:19 Failed validation against schema 2: jsonschema: '' does not validate with http://json-schema.orrg/schema#/required: missing properties: 'name'

@santhosh-tekuri
Copy link
Owner

@saward From the example, it is easier to understand your question.

CompleString internally calls Compiler.AddResourceJson. i.e we are adding a resource for given url and content.

standard meta schemas are treated superior to use added resources and get precedence always.
in your case "http://json-schema.org/schema" refers to latest metaschema. so CompileString is actually ignoring the string you have given and actually compiling draft 2020-12 metaschema.

when you make a spell mistake, then it longer matches with any standard metaschema, so it is actually compiling the schemaString you have given.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants