Validate the shape and allowed ranges
Define a level shape with required fields such as id, width, height, tiles, spawn, exits, and entities. Check that dimensions are positive integers within the game's supported limits, that the tile array has exactly width times height entries, and that every tile uses a known type. Validate entity coordinates against the grid and require unique identifiers for doors, keys, switches, and objectives. A check for a number alone is not enough; reject NaN-like or out-of-range values explicitly.
Keep optional fields separate from required ones. Give an omitted decorative palette a default, but do not silently invent a missing spawn or exit if doing so could change the puzzle. Return errors with a path such as levels[2].entities[4].x so a content author can find the defective field quickly.
Check relationships and playable invariants
After structural validation, check cross-field rules. Every locked door should reference an existing key; every mandatory key should be reachable before its door; an exit should not sit inside a solid tile. Run a path search from the spawn and confirm that required goals can be reached under the game's movement rules. If enemies or moving platforms affect access, use a more specific validator or a playthrough test rather than claiming a simple grid path proves the whole level is solvable.
Fail safely and test the validator itself
MDN notes that JSON.parse throws a SyntaxError when input is not valid JSON, so catch parse failures separately from schema failures. In development, report the exact file and invariant. In a player build, load a known fallback or show a clear unavailable-level state rather than starting from partial data. Maintain fixtures for missing fields, bad references, blocked paths, and a valid small level; the valid fixture guards against a validator that rejects everything.
Questions about game level data validation
Is successful JSON.parse enough to trust a level file?
No. Parsing confirms syntax, not your game-specific shape, ranges, references, or solvability rules. Validate each of those before passing the level to gameplay code.
Should the game repair invalid levels automatically?
Only for safe, unambiguous defaults. If repairing a missing objective or route changes the design, reject the level and use a known fallback instead of hiding the defect.