Class: Metaschema::JsonSchemaGenerator

Inherits:
Object
  • Object
show all
Defined in:
lib/metaschema/json_schema_generator.rb

Overview

Generates JSON Schema (draft-07) from a parsed Metaschema document.

Usage:

ms = Metaschema::Root.from_xml(File.read("metaschema.xml"))
schema = JsonSchemaGenerator.generate(ms)
puts JSON.pretty_generate(schema)

The generator walks the metaschema definition tree and emits a JSON Schema with a top-level object for each root assembly, and shared $defs for all referenced types.

Constant Summary collapse

SCHEMA_URI =
"http://json-schema.org/draft-07/schema#"
TYPE_MAP =

Maps metaschema as-type to JSON Schema type.

{
  "string" => { "type" => "string" },
  "markup-line" => { "type" => "string" },
  "markup-multiline" => { "type" => "string" },
  "boolean" => { "type" => "boolean" },
  "integer" => { "type" => "integer" },
  "positive-integer" => { "type" => "integer", "minimum" => 1 },
  "non-negative-integer" => { "type" => "integer", "minimum" => 0 },
  "decimal" => { "type" => "number" },
  "date" => { "type" => "string", "format" => "date" },
  "date-time" => { "type" => "string", "format" => "date-time" },
  "dateTime" => { "type" => "string", "format" => "date-time" },
  "dateTime-with-timezone" => { "type" => "string",
                                "format" => "date-time" },
  "uri" => { "type" => "string", "format" => "uri" },
  "uri-reference" => { "type" => "string" },
  "uuid" => { "type" => "string",
              "pattern" => "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$" },
  "base64" => { "type" => "string", "contentEncoding" => "base64" },
  "token" => { "type" => "string" },
  "email" => { "type" => "string", "format" => "email" },
  "ip-v4-address" => { "type" => "string", "format" => "ipv4" },
  "ip-v6-address" => { "type" => "string", "format" => "ipv6" },
}.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(metaschema, id: nil) ⇒ JsonSchemaGenerator

Returns a new instance of JsonSchemaGenerator.



49
50
51
52
53
54
55
56
# File 'lib/metaschema/json_schema_generator.rb', line 49

def initialize(metaschema, id: nil)
  @metaschema = metaschema
  @id = id
  @definitions = {}
  @field_defs = {}
  @assembly_defs = {}
  @flag_defs = {}
end

Class Method Details

.generate(metaschema, id: nil) ⇒ Object



45
46
47
# File 'lib/metaschema/json_schema_generator.rb', line 45

def self.generate(metaschema, id: nil)
  new(metaschema, id: id).generate
end

Instance Method Details

#generateObject



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/metaschema/json_schema_generator.rb', line 58

def generate
  collect_definitions

  @metaschema.define_assembly&.each { |a| build_assembly_schema(a) }
  @metaschema.define_field&.each { |f| build_field_def_schema(f) }
  @metaschema.define_flag&.each { |f| build_flag_schema(f) }

  root_assemblies = (@metaschema.define_assembly || []).select do |a|
    a.root_name&.content
  end
  if root_assemblies.one?
    root = root_assemblies.first
    root_name = root.root_name.content
    @definitions[root.name] || { "type" => "object" }

    schema = {
      "$schema" => SCHEMA_URI,
      "$id" => @id,
      "type" => "object",
      "properties" => { root_name => { "$ref" => "#/$defs/#{root.name}" } },
      "required" => [root_name],
      "additionalProperties" => false,
      "$defs" => @definitions,
    }
    schema.delete("$id") unless @id
    schema
  else
    {
      "$schema" => SCHEMA_URI,
      "$id" => @id,
      "$defs" => @definitions,
    }.compact
  end
end