{ "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://polymake.org/schemas/data.json",
  "title": "polymake data objects",
  "description": "polymake data format starting with release 4.0",
  "definitions": {
    "valid_index": {
      "type": "integer",
      "minimum": 0
    },
    "valid_id": {
      "type": "string",
      "pattern": "^[a-zA-Z]\\w*$"
    },
    "valid_attr_name": {
      "type": "string",
      "pattern": "^[_a-zA-Z]\\w*$"
    },
    "valid_qual_id": {
      "description": "Name of a property with an optional namespace prefix.",
      "type": "string",
      "pattern": "^([a-zA-Z]\\w*:)?[a-zA-Z]\\w*$"
    },
    "ext_list": {
      "description": "Extensions needed for a data fragment.\nNumbers refer to the order of definitions in the ns_dict entry.",
      "type": "array",
      "items": { "$ref": "#/definitions/valid_index" },
      "uniqueItems": true
    },
    "ns_dict": {
      "description": "Information about software that created the data instance or parts of it\nKeys defined here are used as namespace prefixes of properties and types in the data instance.",
      "type": "object",
      "properties": {
        "default" : {
          "description": "Namespace to be assumed for all properties and types without a namespace prefix.",
          "$ref": "#/definitions/valid_id"
        }
      },
      "propertyNames": { "$ref": "#/definitions/valid_id" },
      "additionalProperties" : {
        "description": "URI of a software package and its version",
        "type": "array",
        "items": [ {"type": "string"}, {"type": "string"} ],
        "additionalItems": {
          "description": "Extensions of the software package: URI and optional version",
          "type": "array",
          "items": [ {"type": "string"}, {"type": ["string", "null"]} ],
          "additionalItems": false
        }
      },
      "minProperties": 1,
      "dependencies": {
        "default": {
          "minProperties": 2
        }
      }
    },
    "obj_info":  {
      "type": "object",
      "properties": {
        "description": {
          "description": "Human-readable description of the data instance.",
          "type": "string"
        },
        "credits": {
          "description": "References to contributors of extensions and third-party software packages which were used for creation of the data instance.\nMay include URL, authors' names, copyright notes.",
          "type": "object",
          "additionalProperties": { "type": "string" }
        }
      }
    },
    "obj_id": {
       "description": "Name assigned to the data instance.\nMay have to obey to certain syntax rules if used as a unique id in a database or similar collection.\n", 
       "type": [ "string", "integer" ]
    },
    "big_obj": {
      "type": "object",
      "properties": {
        "_id": { "$ref": "#/definitions/obj_id" },
        "_info": {
          "description": "Informational part of the data instance.",
          "$ref": "#/definitions/obj_info"
        },
        "_type": {
          "description": "Type of the data instance, qualified with module/library/component name prefix if applicable.",
          "type": "string"
        },
        "_load": {
          "description": "Additional modules/libraries/components contributing single properties to this data instance\nif they are not automatically included by the main module where the object type is defined.\n",
          "type" : "array",
          "items": { "type": "string" }
        },
        "_ext": {
          "description": "Extensions necessary for instantiation of the data instance type.",
          "$ref": "#/definitions/ext_list"
        },
        "_attrs": {
          "description": "Attributes of certain object properties which are necessary for proper decoding of their values.",
          "type": "object",
          "propertyNames": { "$ref": "#/definitions/valid_attr_name" },
          "additionalProperties": {
            "type": "object",
            "properties": {
              "_type": {
                "description": "Type of the property value when it differs from the default type assumed by the data model.",
                "type": "string"
              },
              "_ext": {
                "description": "Extensions introducing the property and/or necessary for instantiation of its value type.",
                "$ref": "#/definitions/ext_list"
              },
              "attachment": {
                "description": "Designates a property as an optional attachment without fixed semantics.",
                "type": "boolean",
                "default": false
              },
              "method": {
                "description": "Designates a property as a result of a method call, persisted only upon explicit request.",
                "type": "boolean",
                "default": false
              }
            },
            "if": { "properties": { "attachment": { "const": true } } },
            "then": {
              "properties": {
                "construct": {
                  "description": "Properties to be passed to the constructor of an attachment.",
                  "type": [ "string", "array" ],
                  "items": { "type": "string" },
                  "minItems": 1
                }
              }
            }
          }
        }
      }
    },
    "top_level": {
      "description": "Properties mandatory for the top level of the data file.",
      "type": "object",
      "properties": {
        "_ns": { "$ref" : "#/definitions/ns_dict" },
        "_canonical": {
          "type": "boolean",
          "default": false
        }
      },
      "required": [ "_type", "_ns" ]
    }
  },
  "allOf": [
    { "$ref": "#/definitions/top_level" },
    { "oneOf": [
        { "description": "Single object",
          "$ref": "#/definitions/big_obj"
        },
        { "description": "Anonymous list of objects",
          "properties": {
            "data": {
              "type": "array",
              "items": { "$ref": "#/definitions/big_obj" }
            },
            "_type": { "type": "null" }
          },
          "required": [ "data" ]
        },
        { "description": "Anonymous map of objects",
          "properties": {
            "data": {
              "type": "object",
              "additionalProperties": { "$ref": "#/definitions/big_obj" }
            },
            "_type": { "type": "null" }
          },
          "required": [ "data" ]
        }
      ]
    }
  ]
}
