`Compiler.AddResource` for adding pre-compiled schemas
Opened this issue · 5 comments
Is it possible to perform something equivalent to Compiler.AddResource
but for a pre-compiled schema? In my application, I have a number of schemas already compiled with jsonschema.MustCompileString
for other uses. It would be good to be able to reuse these in another schema with $ref
references pointing at them without needing to re-add and recompile their schemas from strings.
I'm current implementing the solutions described at #89 (comment), but each operates on the schema's raw characters.
Adding the following to compiler.go
allows my cross-referenced schema to compile, though I don't know if it's sufficiently creating a resource
internally:
// AddResourceSchema adds a pre-compiled *Schema to the compiler.
func (c *Compiler) AddResourceSchema(url string, sch *Schema) {
c.resources[url] = &resource{
url: url,
draft: sch.Draft,
schema: sch,
}
}
This function probably wants to be checking for sch == nil
and return an error.
you can not do that. But you can do the following.
add all your resources into single compiler and then compile each one sequentially; for example:
resources = map[string]string { ....}
c := jsonschema.NewCompiler()
for url, content := range resources {
if err:=c.AddResource(url, strings.NewReader(content)); err!=nil {
panic(err)
}
}
schemas := map[string]*jsonschema.Schema{}
for url := range resources {
sch, err := c.Compile(url)
if err!=nil {
panic(err)
}
schemas[url] = sch
}
there is no restrictions that all resources should be added before compile if they are independent. you can compile and then add new resources which has $ref
to previously compiled and then compile the newly added resources.
as long as you use same Compiler
instance, any new resources added can reference to previously compiled schemas
c := jsonschema.NewCompiler()
if err := c.AddResource("schema1.json", strings.newReader("{}"); err!=nil {
panic(err)
}
sch1, err := c.Compile("schema1.json")
if err!=nil {
panic(err)
}
sch1_again, err := c.Compile("schema1.json") // compiling same schema simply returns previously compiled schema
if err!=nil {
panic(err)
}
// now sch1 and sch1_again both point to same schema struct
// now you can add another resource which has $ref to schema1.json
if err := c.AddResource("schema2.json", strings.newReader(`{"$ref": "schema1.json"}`); err!=nil {
panic(err)
}
sch2, err := c.Compile("schema2.json")
if err!=nil {
panic(err)
}
Thanks @santhosh-tekuri, I really appreciate it - the first is effectively what I've implemented at the moment but the second is an interesting idea - I didn't realise the internals of "re-compiling" the same schema.
In my case, I was endeavouring to have separation between compilation of schemas where possible so each is a clean environment, and then referencing the the pre-compiled schemas in separate code. Also, I'd aimed to do as much as possible at the top level in a module, avoiding the need for init()
if possible and the boilerplate for checking err
and panic
king.
Is something like AddResourceSchema
feasible? As I say, I've only tested the compilation process with the example above but the $ref
entries do appear to resolve.
it is not that straight forward for what you are asking. let us say:
schema1.json is:
{
"$def": {
"a": ...,
"b": ...,
}
}
here when you compile schema1.json
then only schema1.json
is compiled.
schema1.json#/$def/a
and schema1.json#/$def/a
are not compiled
so if you add schema2.json:
{
"$ref": "schema1.json#/$def/a"
}
now compiling schema2.json works correctly if you have used same Compiler
as you suggested, if you create new Compiler
and somehow add schema1 compiled schema to it, still it won't resolve the $ref
in schema2.json
. I hope you got my point.
Thanks @santhosh-tekuri, I really appreciate it - the first is effectively what I've implemented at the moment but the second is an interesting idea - I didn't realise the internals of "re-compiling" the same schema.
it does not recompile, before compiling we check if it is already precompiled, if so we return the precompiled schema again.
see https://github.com/santhosh-tekuri/jsonschema/blob/master/compiler.go#L284-L289