notEthan / jsi

JSI: JSON Schema Instantiation in Ruby
Other
22 stars 1 forks source link

How to register new meta schema? #339

Closed ixti closed 1 month ago

ixti commented 2 months ago

I want to use JSI for Snowplow's self-describing json schemas:

{
    "$schema": "http://iglucentral.com/schemas/com.snowplowanalytics.self-desc/schema/jsonschema/1-0-0#",
    "description": "A template for a self-describing JSON Schema for use with Iglu",
    "self": {
        "vendor": "com.myvendor",
        "name": "myschema",
        "format": "jsonschema",
        "version": "1-0-0"
    },

    "type": "object",

    "properties": {

        "myStringProperty": {
            "type": "string"
        },

        "myNumberProperty": {
            "type": "number"
        }
    },

    "required": ["myStringProperty", "myNumberProperty"],
    "additionalProperties": false
}

Loading this schema directly fails with:

gems/addressable-2.8.6/lib/addressable/uri.rb:918:in `scheme=': stack level too deep (SystemStackError)

So I tried:

JSI.new_metaschema_module(
  HTTP.get("http://iglucentral.com/schemas/com.snowplowanalytics.self-desc/schema/jsonschema/1-0-0").parse(:json),
  schema_implementation_modules: [JSI::Schema::Draft04]
)

But that also fails. with:

could not resolve remote ref with no schema_registry specified (JSI::Schema::ReferenceError)
ref URI: http://json-schema.org/draft-04/schema#
from: #<JSI::MetaSchemaNode::BootstrapSchema (JSI::Schema::Draft04) #/allOf/1
  {"$ref"=>"http://json-schema.org/draft-04/schema#"}
>
notEthan commented 2 months ago

This is interesting, I have not come across a schema quite like this before.

One difficulty is that the snowplow schema does not have an id, and JSI is currently not able to resolve a $schema to a meta-schema without that. The other problem is resolving remote references (the "$ref": "http://json-schema.org/draft-04/schema#") isn't supported for a meta-schema yet (though that part will be supported next release).

For now, to make a construction that should be good enough for most purposes, I would disregard its $schema and instantiate this as a draft 4 schema, and then indicate that it also describes a draft 4 schema:

SnowplowMetaSchema = JSI::JSONSchemaDraft04.new_schema_module(
  JSON.parse(Net::HTTP.get(URI("http://iglucentral.com/schemas/com.snowplowanalytics.self-desc/schema/jsonschema/1-0-0"))),
  uri: "http://iglucentral.com/schemas/com.snowplowanalytics.self-desc/schema/jsonschema/1-0-0"
)
SnowplowMetaSchema.schema.describes_schema!([JSI::Schema::Draft04])

Then you can make schemas that are instances of that.

snowplow_schema = SnowplowMetaSchema.new_schema({'self' => {...}})
# or
snowplow_schema = JSI.new_schema({
  '$schema' => "http://iglucentral.com/schemas/com.snowplowanalytics.self-desc/schema/jsonschema/1-0-0", 
  'self' => {...}
})

I think that is as correct as I can make it. SnowplowMetaSchema's schema isn't self-describing (that is, not an an instance of itself - I feel they are using the term 'self-describing' somewhat differently), though you could make an instance of its own content, i.e. SnowplowMetaSchema.new_schema(SnowplowMetaSchema.schema_content). This is probably not an important distinction.

I'll also note that the interface of describes_schema! will change - I expect the above to work until JSI 1.0. (I'm finalizing support for JSON Schema draft 2020-12 which involves significant architecture change, which affects describes_schema!, to accommodate its specification of vocabularies.)

notEthan commented 2 months ago

Oh, I am also curious what led to that SystemStackError - could you show me the code that produced that error? I can't figure out how that would happen.

ixti commented 2 months ago

Hm. I can't reproduce SystemStackError. But as I was toying around with json_schemer at the same time (with no success either), I have a feeling I have confused the error a bit. Sorry for the false alarm.

notEthan commented 1 month ago

All good. Did the above code help you get this going?

ixti commented 1 month ago

Works like a charm!!! Thank you!

notEthan commented 1 month ago

Wonderful!