{
    "$ref": "#/definitions/canonicalData",
    "$schema": "http://json-schema.org/draft-04/schema#",
    "comments": [
        " This is a JSON Schema for 'canonical-data.json' files.     ",
        "                                                            ",
        " It enforces just a general structure for all exercises,    ",
        " optimising for the ability to represent example-based tests",
        " of the form 'function (input) == output'. Future expansions",
        " may allow for other types of tests such as property-based. ",
        "                                                            ",
        " The only thing enforced regarding how test data should be  ",
        " structured is the error encoding, because it was agreed    ",
        " and it doesn't restrict flexibility in a significant way.  ",
        "                                                            ",
        " Standardized property names may help when automatically    ",
        " deriving JSON parsers in some languages, so we followed    ",
        " a few conventions from the 'Google JSON Style Guide'.      ",
        "                                                            ",
        " Additionally, this schema strictly enforces letters, in    ",
        " lowerCamelCase, for naming the 'property' being tested. We ",
        " expect this regularity will allow an easier automatic      ",
        " generation of function's names in test generators,         ",
        " slightly reducing the amount of manually generated code.   "
    ],
    "definitions": {
        "canonicalData": {
            "additionalProperties": false,
            "description": "This is the top-level file structure",
            "properties": {
                "cases": {
                    "$ref": "#/definitions/testGroup"
                },
                "comments": {
                    "$ref": "#/definitions/comments"
                },
                "exercise": {
                    "$ref": "#/definitions/exercise"
                },
                "version": {
                    "$ref": "#/definitions/version"
                }
            },
            "required": [
                "exercise",
                "version",
                "cases"
            ],
            "type": "object"
        },
        "comments": {
            "description": "An array of strings to fake multi-line comments",
            "items": {
                "type": "string"
            },
            "minItems": 1,
            "type": "array"
        },
        "description": {
            "description": "A short, clear, one-line description",
            "type": "string"
        },
        "error": {
            "description": "A message describing an error condition",
            "type": "string"
        },
        "exercise": {
            "description": "Exercise's slug (kebab-case)",
            "pattern": "^[a-z]+(-[a-z]+)*$",
            "type": "string"
        },
        "expected": {
            "dependencies": {
                "error": {
                    "maxProperties": 1
                }
            },
            "description": "The expected return value of a test case",
            "properties": {
                "error": {
                    "$ref": "#/definitions/error"
                }
            }
        },
        "input": {
            "description": "The inputs to a test case",
            "type": "object"
        },
        "labeledTest": {
            "additionalProperties": false,
            "description": "A single test with a description",
            "properties": {
                "comments": {
                    "$ref": "#/definitions/comments"
                },
                "description": {
                    "$ref": "#/definitions/description"
                },
                "expected": {
                    "$ref": "#/definitions/expected"
                },
                "input": {
                    "$ref": "#/definitions/input"
                },
                "optional": {
                    "$ref": "#/definitions/optional"
                },
                "property": {
                    "$ref": "#/definitions/property"
                }
            },
            "required": [
                "description",
                "property",
                "input",
                "expected"
            ],
            "type": "object"
        },
        "labeledTestGroup": {
            "additionalProperties": false,
            "description": "A group of tests with a description",
            "properties": {
                "cases": {
                    "$ref": "#/definitions/testGroup"
                },
                "comments": {
                    "$ref": "#/definitions/comments"
                },
                "description": {
                    "$ref": "#/definitions/description"
                },
                "optional": {
                    "$ref": "#/definitions/optional"
                }
            },
            "required": [
                "description",
                "cases"
            ],
            "type": "object"
        },
        "labeledTestItem": {
            "description": "A single test or group of tests with a description",
            "oneOf": [
                {
                    "$ref": "#/definitions/labeledTest"
                },
                {
                    "$ref": "#/definitions/labeledTestGroup"
                }
            ]
        },
        "optional": {
            "description": "An identifier for similar optional test cases (kebab-case)",
            "pattern": "^[a-z]+(-[a-z]+)*$",
            "type": "string"
        },
        "property": {
            "description": "A letters-only, lowerCamelCase property name",
            "pattern": "^[a-z]+([A-Z][a-z]+)*[A-Z]?$",
            "type": "string"
        },
        "testGroup": {
            "description": "An array of labeled test items",
            "items": {
                "$ref": "#/definitions/labeledTestItem"
            },
            "minItems": 1,
            "type": "array"
        },
        "version": {
            "description": "Semantic versioning: MAJOR.MINOR.PATCH",
            "pattern": "^(0|[1-9][0-9]*)(\\.(0|[1-9][0-9]*)){2}$",
            "type": "string"
        }
    },
    "self": {
        "format": "jsonschema",
        "name": "canonical-data",
        "vendor": "io.exercism",
        "version": "1-1-0"
    }
}