xeipuuv / gojsonschema

An implementation of JSON Schema, draft v4 v6 & v7 - Go language
2.56k stars 358 forks source link

Question: How to use embed.FS with References? #330

Open neumachen opened 3 years ago

neumachen commented 3 years ago

So, I'm quite familiar with JSON schemas and sadly, the past 3-4 years I've been doing using this package, I just literally copy paste schemas so I never use the reference. But this needs to change and I was hoping to be able to fully leverage the reference with JSON schemas which I know this package can do but I'm not entirely sure how to go on about this with Go's embed directive.

Let's say I have generic schemas for resources like addresses, phone numbers, etc that's in a package. How can I use those definitions in another JSON schema using this package?

example:

{

   address: {
     "$ref": "file://some-package/address.json"
    }
}

Any ideas on how to solve this?

Emyrk commented 3 years ago

This is what I have done.

schemas/address.schema.json

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "definitions": {
    "allowed_string_map": {
      "$id": "#address",
      "type": "object",
      "properties": {
        "city": {"type": "string"},
        "state": {"type": "string"}
      }
    }
  }
}

Then you just load the loader using the filename expected.


//go:embed schemas/*.json
var JsonSchemas embed.FS

func load() {
    dir := "schemas"
    all, _ := JsonSchemas.ReadDir(dir)
    loader := gojsonschema.NewSchemaLoader()
    for _, f := range all { // Add all static files to loader
        data, _ := JsonSchemas.ReadFile(filepath.Join(dir, f.Name()))
        fileLoader := gojsonschema.NewBytesLoader(data)
        loader.AddSchema(f.Name(), fileLoader)
    }

    schema, _ := loader.Compile(gojsonschema.NewStringLoader(`
{
   "properties": {
    "address": {"$ref": "address.schema.json#address"}
    }
}`))

    var _ = schema // Use the schema to validate
}
daveshanley commented 2 years ago

@Emyrk super helpful, thank you!