jsonschema
jsonschema copied to clipboard
Expose the schema of a resource while being compiled by an extension compiler
Sometimes an extension compiler needs to collect metadata about the instance of the keyword being compiled - most notably, its location. With the proposed method, one can collect the location of the keyword in the compiler method like so:
func (c myCompiler) Compile(ctx jsonschema.CompilerContext, m map[string]interface{}) (jsonschema.ExtSchema, error) {
if v, ok := m["myKeyword"]; ok {
location := ctx.GetResourceSchema().Location
...
}
...
}
Can you explain the use case why you need schema location in your case.
Ideally only keywords like $ref need such case. To handle such use cases we already have CompilerContext CompileRef
Here's an example: One of the schema extensions I am building, uses external meta information stored in a map provided to the extension compiler. When the compiler compiles a given instance of the extension keyword, it needs to lookup this map based on the location of the keyword in the schema. The provided metadata is attached to the compiled schema and it is used by the schema's Validate method.
Can you give specific example.
I see none of the keywords in specification require this info
I see none of the keywords in specification require this info
I'm not sure what you mean by this. The example I gave above is specific to the validation I am building. That validation revolves around testing the validity of data based on an external piece of information which is stored in a dictionary whose keys are the paths to the schema elements that use the extension keyword. I am afraid I am not in a position to disclose more than this. I was hoping to make it clear that there are use cases where extension developers might need more from the compilation context than just the action methods it provides.
@santhosh-tekuri can you please provide an example of how to use CompilerContext
@debuggerpk
for simple keywords like shown in example, you will not need CompilerContext
but if you want to implement keywords that have:
- subschemas. for example
propertieskeyword;CompilerContext.Compilemethod used in this case - refere to other subschemas. for example
$refkeyword;CompileContext.CompileRefmethod used in this case
consider an example of implementing discriminator keyword; let us say you have array of vehicles as shown below:
[
{
"kind": "fuelled-vehicle",
"fuel": "petrol"
},
{
"kind": "electric-vehicle",
"battery-capacity": "4000mah"
}
]
we support two types of vehicles, fuelled-vehicle and electric-vehicle each has its own properties
based on the value of kind property you want to validate with specific vehicle type.
we can implement discriminator keyword for this:
{
"type": "array",
"items": {
"discriminator": {
"kind": {
"fuelled-vehicle": {
"type": "object",
"required": ["fuel"]
},
"electric-vehicle": {
"type": "object",
"required": ["battery-capacity"]
}
}
}
}
}
below is the implementation:
type discriminator struct {
property string
valueSchemas map[string]*Schema
}
func (d * discriminator) Compile(ctx jsonschema.CompilerContext, m map[string]interface{}) (jsonschema.ExtSchema, error) {
v, ok := m["discriminator"]
If !ok {
return nil, nil
}
vmap, ok := v.(map[string]interface{})
if !ok {
return nil, nil
}
for pname, pvalue := range map {
d.property = name
obj := value.(map[string]interface{})
for value, _ := range obj {
sch, err = ctx.Compile("discriminator/"+value, true)
if err!=nil {
return nil, err
}
d.valueSchemas[value] = such
}
break
}
}
suppose you want discriminator always refer to other schemas as shown below:
{
"$defs": {
"fuelled-vehicle": {
"type": "object",
"required": ["fuel"]
},
"electric-vehicle": {
"type": "object",
"required": ["battery-capacity"]
}
}
"type": "array",
"items": {
"discriminator": {
"kind": {
"fuelled-vehicle": "#/$defs/fuelled-vehicle",
"electric-vehicle": "#/$defs/electric-vehicle",
}
}
}
}
to implement this you use CompilerContext.CompileRef instead of CompilerContext.Compile in above implementation as below:
func (d * discriminator) Compile(ctx jsonschema.CompilerContext, m map[string]interface{}) (jsonschema.ExtSchema, error) {
v, ok := m["discriminator"]
If !ok {
return nil, nil
}
vmap, ok := v.(map[string]interface{})
if !ok {
return nil, nil
}
for pname, pvalue := range map {
d.property = name
obj := value.(map[string]interface{})
for value, ref := range obj {
sch, err = ctx.CompileRef(ref, "discriminator/"+value, true)
if err!=nil {
return nil, err
}
d.valueSchemas[value] = such
}
break
}
}
note that, I have not tested this functionality myself. but this is how it is supposed to be used.
I am looking to bump cdevents https://github.com/cdevents/sdk-go to version 4. The error comes because this line https://github.com/cdevents/spec/blob/v0.4.0/schemas/artifactdeleted.json#L41
the "$ref": "/schema/links/embeddedlinksarray.json" is a reference to the respected file in the relative links forlder, but the loader cannot find the file. I guess the schema is not published.
I am looking for a way to create a map at compile time. i can use the map aswell, right?
// ysf
@debuggerpk please ask the question in Discussions
That will help others with similar question. I will answer it there.
Sorry for late reply. Link to discussion.