Generate a JSON schema

This utility generates a JSON Schema document from a SHACL specification. Detailed documentation is available below.

  Shapes

Remove Select file Change
You can select multiple files. Supported extensions : .rdf, .ttl, .n3, .trig, or .zip. You can also upload Excel files (see SHACL in Excel).
URL of an RDF file. Same extensions as file upload are supported.
Supported syntaxes : Turtle, RDF/XML, JSON-LD, TriG, TriX, N-Quads. We recommend Turtle.

  Options

If known, the JSON-LD context with which the generated JSON schema will be used. This is exactly the value of the "@context" property (without "@context" itself).
The URI of the Node Shape that will be used as root in the JSON schema generation. First select your SHACL file above, and click here to list all NodeShapes URI.
By default, SHACL Play! will use native JSON types in the generated JSON schema. For example, a property with xsd:integer datatype will be mapped to 'number' in the JSON schema. If you check this option, all properties will be represented as strings in the JSON schema, even if they have a specific datatype in the SHACL file. This can be useful if your generated JSON-LD does not use native types.
This is useful when your SHACL specification contains values or list of values that are subject to change. By not including them in the schema, the list of values can evolve over time without impacting the users of the generated schema.
This is useful when the schema can evolve and new properties can be added. Entities with these new properties will not break an old schema already used by users.

Documentation

JSON Schema generation from SHACL

The algorithm follow these steps to generate the JSON Schema:

Constant declarations
  • A declaration is always added for @context since we are targeting JSON-LD
  • schema version is always set to https://json-schema.org/draft/2020-12/schema
  • a container_language declaration is always added with a patternProperty declaration with properties being language codes to deal with "@container": "language" properties.
Schema header
  • title is populated from an owl:Ontology dct:title or rdfs:label
  • version is populated from an owl:Ontology owl:versionInfo
  • description is populated from an owl:Ontology dct:description
Node shapes conversion

The Shapes Graph is cleaned so that Node Shapes that are not references from any where and that don't have any properties attached are removed.

A pure value shape is a shape that has no non-deactivated attached properties (directly or through inheritance), and no target defined.

Each node shape that is not a pure value shape is turned into an object schema in the $defs section of the schema, with the URI local name as the name of the schema. Node shapes that are pure value shape will be turned into string schemas being simple iri-reference.

  • title is populated from the node shape rdfs:label
  • description is populated from the node shape rdfs:comment
  • There is always a required id property
  • Pattern processing:
    • If the node shape holds (directly or through inheritance) a property shape tagged with shui:propertyRole shuiIDRole and this property has a sh:pattern, it is considered the pattern of the short form of the URI in the schema, and it is used for the pattern constraint on the id key.
    • Otherwise, if there is an sh:node*/sh:pattern associated to the node shape (meaning, directly or through inheritance), it is turned into a pattern constraint on the id key, after attempting to reduce the pattern using the context (e.g. remove base URI)
  • If there is a sh:node*/skos:example associated to the node shape (meaning, directly or through inheritance), it is turned into an example constraint on the id key
  • If node shape is closed, then additionalProperties is set to false, except if the flag "never set additional properties" is set.
  • Then each non-deactivated property shape reachable through sh:node*/sh:property (meaning, directly or through inheritance) is processed as described below
Property shapes conversion

Non-deactivated property shapes are processed this way:

  • If a JSON-LD context was provided, it is probed to determine the term for the property. The context probing works if it matches the property @type in the context (either an @id property, or the datatype for literal properties).
  • If context was not provided, the corresponding JSON key is read from shacl-play:shortName annotation, otherwise the local name of the property in sh:path is used as the JSON key
  • The property shape is mapped to a schema this way:
    • If the property shape has an sh:hasValue, a const schema is created with the value. If a JSON-LD context was provided, an attempt is made to simplify the value to its actual mapping from the context, either because it is directly declared in the vocab, or because a prefix is declared.
    • If the property shape has an sh:in, an enum schema is created with the list of possible values. If a JSON-LD context was provided, an attempt is made to simplify the list of possible values to their actual mapping from the context, either because they are directly declared in the vocab, or because a prefix is declared.
    • If the property shape has an sh:node, then :
      • If this sh:node reference is a pure value shape, don't do anything specific, as further steps will take care of it
      • Otherwise if the property shape is annotated with shacl-play:embed shacl-play:EmbedNever, then a string schema with format iri-reference is generated
      • Otherwise, create a $ref schema with a reference to one of the schemas in the #/$defs section
    • If no schema were returned by the previous steps, then:
      • If a (sh:node*)/sh:pattern exists (i.e. attached directly to the property shape or through inheritance), and if the datatype of the property is not rdf:langString nor xsd:integer, then turn it into a string schema with a pattern constraint. If a JSON-LD context was provided, the pattern constraint is "reduced" so that patterns matching complete IRIs may match only the end of IRI if they are shortened due to @base in the context
      • If the property shape has an (sh:node*)/sh:datatype (i.e. attached directly to the property shape or through inheritance), or an sh:qualifiedValueShape that has an sh:datatype then:
      • If the property shape has an (sh:node*)/sh:nodeKind (i.e. attached directly to the property shape or through inheritance) then
        • if it is sh:IRI, generate a string schema of format iri-reference.
        • if it is sh:Literal, generate a string schema.
      • If the property shape has an (sh:node*)/sh:example (i.e. attached directly to the property shape or through inheritance) attempt to reduce them with the context and put them in "examples".
    • If still nothing, then use an empty schema
    • Then the algorithm determines whether the property requires an array:
      • If a JSON-LD context was provided, and if the context does not require a @container: language, then:
        • if there is a sh:qualifiedMaxCount and it is > 1, then wrap the generated schema into an array schema
        • if there is no sh:maxCount or a sh:maxCount that is > 1, then wrap the generated schema into an array schema
      • If still not an array, try to compact a test of the property with the JSON-LD context to determine if the context mandates a @container : @set. If the compaction test returns an array, then an array will be declared in the output schema.
    • title is populated from the property shape sh:name
    • description is populated from the property shape sh:description
  • If the sh:minCount, or the sh:qualifiedMinCount of the property is > 0, the JSON key is added to the list of requiredProperties of the schema
Root node shape

With the provided root node shape IRI, create a reference to the corresponding schema from the #/$defs section.