brandur/json_schema

Can't refer to external file?

gjtorikian opened this issue · 6 comments

I'd like to be able to split up my jumbo JSON into a smaller file, using references like this:

"$ref": "file://schemas/json/file.json"

It looks like Evaluator's enforcement of / as the first char prevents this from happening. Is there any way this can be achieved?

Hello!

You should be able to do this by (1) assigning your external schema a simple URI identifier, (2) referencing that identifier from your schema, and (3) making sure to load the external schema into your document store when expanding references.

For example, if you were going to use the built-in validate-schema command, you could have your external schema as testschema/external-schema.json:

{
    "id": "http://brandur.org/external-schema#"
}

Your main schema as testschema/schema.json:

{
    "id": "http://brandur.org/schema#",
    "allOf": [
        {
            "$ref": "http://brandur.org/external-schema#"
        }
    ]
}

And some data you wanted to validate as testschema/data.json:

{
    "$schema": "http://brandur.org/schema#"
}

Then this would be run as:

bin/validate-schema -d -s testschema/external-schema.json -s testschema/schema.json testschema/data.json

Without the built in command, this would essentially look like adding files to a DocumentStore instance, then passing that instance when calling the ReferenceExpander.

@brandur I'd like to do the same thing as @gjtorikian . In particular I'd like to do it for use with Committee:

 schema = JSON.parse(File.read(...))
 use Committee::Middleware::RequestValidation, schema: schema
 use Committee::Middleware::ResponseValidation, schema: schema

Where the (hyper)schema in question might separate each request or response schema into its own file

"links": [
    {
      "description": "Create a widget",
      "href": "/widgets",
      "method": "POST",
      "rel": "create",
      "title": "Create Widget",
      "schema": { "$ref": "<<URI-to-request-schema>>" },
      "targetSchema": { "$ref": "<<URI-to-response-schema>>" }
    },
    ...
   ]

Could you re-cast your example to explain how I could accomplish that? I'm not certain what do do about all that DocumentStore stuff in the context of configuring Committee. Plus, those external schemas I refer to by URI may themselves in turn refer to other external schemas (e.g. a schema with the json description of a Widget), but I wouldn't know in advance exactly where those are so would be hard to pre-load.

Thanks for your help!

Without the built in command, this would essentially look like adding files to a DocumentStore instance, then passing that instance when calling the ReferenceExpander.

Awesome, this comment got me back on track. I'm not using the command line instance so this was useful for me to go and dig around on my own.

@ronen What I've done for DocumentStore is something like:

document_store = JsonSchema::DocumentStore.new
Dir.glob("#{SUBSCHEMA_DIR}/**/*.json").each do |path|
  schema_data = Json.parse(File.read(path))
  extra_schema = JsonSchema.parse!(schema_data)
  document_store.add_schema(extra_schema)
end

   ...

schema_data = Json.parse(File.read(master_json))
schema = JsonSchema.parse!(schema_data)
schema.expand_references!(:store => document_store)

Hopefully that'll help you out. I'm closing this issue (to reduce clutter) but happy to lend a hand if I can.

@gjtorikian Thanks, that helps clarify somewhat. It doesn't solve the problem specifically with Committee (which doesn't document any options regarding document stores), but I'll go open an issue over there :)

@brandur is there a way to reference a local schema file ?

@vasilakisfil Hey! Yes, you should be able to do it using the instructions above. See my comment here for information on the general strategy and @gjtorikian's comment here for code on using the DocumentStore programmatically.