The schema was added before the Hindi (73b0c68) and Polish/Korean (118e4bd) instructions landed, so languageMap and languageStepsMap still only declared en, es, it, tr, ru, zh. All 1,324 records carry all nine languages and the README documents nine, but `additionalProperties` let hi/pl/ko through unvalidated and unrequired — a record silently missing them still passed validation. Declare all nine in `properties` and `required` for both maps. Verified: the 1,324 records validate cleanly against the updated schema, and a record missing hi/pl/ko is now rejected.
158 lines
4.9 KiB
JSON
158 lines
4.9 KiB
JSON
{
|
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
"$id": "https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.schema.json",
|
|
"title": "Exercises Dataset",
|
|
"description": "Schema for data/exercises.json — an array of fitness exercise records with multilingual instructions and media references.",
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/$defs/exercise"
|
|
},
|
|
"$defs": {
|
|
"languageMap": {
|
|
"type": "object",
|
|
"description": "Instruction text keyed by ISO 639-1 language code.",
|
|
"properties": {
|
|
"en": { "type": "string" },
|
|
"es": { "type": "string" },
|
|
"it": { "type": "string" },
|
|
"tr": { "type": "string" },
|
|
"ru": { "type": "string" },
|
|
"zh": { "type": "string" },
|
|
"hi": { "type": "string" },
|
|
"pl": { "type": "string" },
|
|
"ko": { "type": "string" }
|
|
},
|
|
"required": ["en", "es", "it", "tr", "ru", "zh", "hi", "pl", "ko"],
|
|
"additionalProperties": { "type": "string" }
|
|
},
|
|
"languageStepsMap": {
|
|
"type": "object",
|
|
"description": "Step-by-step instructions as an array of strings, keyed by ISO 639-1 language code.",
|
|
"properties": {
|
|
"en": { "$ref": "#/$defs/steps" },
|
|
"es": { "$ref": "#/$defs/steps" },
|
|
"it": { "$ref": "#/$defs/steps" },
|
|
"tr": { "$ref": "#/$defs/steps" },
|
|
"ru": { "$ref": "#/$defs/steps" },
|
|
"zh": { "$ref": "#/$defs/steps" },
|
|
"hi": { "$ref": "#/$defs/steps" },
|
|
"pl": { "$ref": "#/$defs/steps" },
|
|
"ko": { "$ref": "#/$defs/steps" }
|
|
},
|
|
"required": ["en", "es", "it", "tr", "ru", "zh", "hi", "pl", "ko"],
|
|
"additionalProperties": { "$ref": "#/$defs/steps" }
|
|
},
|
|
"steps": {
|
|
"type": "array",
|
|
"items": { "type": "string", "minLength": 1 }
|
|
},
|
|
"exercise": {
|
|
"type": "object",
|
|
"properties": {
|
|
"id": {
|
|
"type": "string",
|
|
"description": "Unique numeric identifier, zero-padded to 4 digits (e.g. \"0001\").",
|
|
"pattern": "^[0-9]{4}$"
|
|
},
|
|
"name": {
|
|
"type": "string",
|
|
"description": "Full exercise name (e.g. \"3/4 sit-up\").",
|
|
"minLength": 1
|
|
},
|
|
"category": {
|
|
"type": "string",
|
|
"description": "Body part category. Mirrors body_part.",
|
|
"minLength": 1
|
|
},
|
|
"body_part": {
|
|
"type": "string",
|
|
"description": "Body part targeted.",
|
|
"enum": [
|
|
"back",
|
|
"cardio",
|
|
"chest",
|
|
"lower arms",
|
|
"lower legs",
|
|
"neck",
|
|
"shoulders",
|
|
"upper arms",
|
|
"upper legs",
|
|
"waist"
|
|
]
|
|
},
|
|
"equipment": {
|
|
"type": "string",
|
|
"description": "Required equipment (e.g. \"dumbbell\", \"body weight\").",
|
|
"minLength": 1
|
|
},
|
|
"instructions": {
|
|
"$ref": "#/$defs/languageMap",
|
|
"description": "Full step-by-step instructions as a single string per language."
|
|
},
|
|
"instruction_steps": {
|
|
"$ref": "#/$defs/languageStepsMap",
|
|
"description": "Same instructions split into an ordered array of steps per language."
|
|
},
|
|
"muscle_group": {
|
|
"type": "string",
|
|
"description": "Primary synergist muscle group.",
|
|
"minLength": 1
|
|
},
|
|
"secondary_muscles": {
|
|
"type": "array",
|
|
"description": "Additional muscles involved.",
|
|
"items": { "type": "string", "minLength": 1 }
|
|
},
|
|
"target": {
|
|
"type": "string",
|
|
"description": "Primary target muscle (e.g. \"biceps\", \"abs\").",
|
|
"minLength": 1
|
|
},
|
|
"media_id": {
|
|
"type": "string",
|
|
"description": "Original media reference id (e.g. \"2gPfomN\").",
|
|
"minLength": 1
|
|
},
|
|
"image": {
|
|
"type": "string",
|
|
"description": "Path to the 180x180 thumbnail (e.g. \"images/0001-2gPfomN.jpg\").",
|
|
"pattern": "^images/.+\\.(jpg|jpeg|png)$"
|
|
},
|
|
"gif_url": {
|
|
"type": "string",
|
|
"description": "Path to the 180x180 animation GIF (e.g. \"videos/0001-2gPfomN.gif\").",
|
|
"pattern": "^videos/.+\\.gif$"
|
|
},
|
|
"attribution": {
|
|
"type": "string",
|
|
"description": "Media copyright notice.",
|
|
"minLength": 1
|
|
},
|
|
"created_at": {
|
|
"type": "string",
|
|
"description": "ISO 8601 timestamp of record creation.",
|
|
"format": "date-time"
|
|
}
|
|
},
|
|
"required": [
|
|
"id",
|
|
"name",
|
|
"category",
|
|
"body_part",
|
|
"equipment",
|
|
"instructions",
|
|
"instruction_steps",
|
|
"muscle_group",
|
|
"secondary_muscles",
|
|
"target",
|
|
"media_id",
|
|
"image",
|
|
"gif_url",
|
|
"attribution",
|
|
"created_at"
|
|
],
|
|
"additionalProperties": false
|
|
}
|
|
}
|
|
}
|