JSON in Game Development: Why Data-Driven Design Wins
JSON in game development means describing your game's content — levels, items, enemy stats, balancing, configuration, and save files — as structured text the engine reads at runtime instead of hardcoding it in source. That separation is called data-driven design, and it is why a designer can rebalance a weapon without an engineer recompiling, why save files and modding become tractable, and why one codebase can ship a hundred levels. JSON (defined by RFC 8259) is the most common carrier because it is plain text, human-readable, easy to diff in version control, and parseable in any language. This explainer covers what JSON is, what data-driven design is, what belongs in a JSON file, where JSON costs you, how the major engines use it, and how it relates to binary formats such as FlatBuffers and Protocol Buffers.
JSON in game development means describing your game's content — levels, items, enemy stats, balancing, configuration, and save files — as structured text the engine reads at runtime, instead of hardcoding it in source. That separation between data and code is called data-driven design, and it is the single practice that turns a programmer-only workflow into one where a designer can rebalance a weapon, add a level, or fix a typo without an engineer rebuilding the game. JSON is the most common format for carrying that data because it is plain text, human-readable, easy to diff in version control, and parseable in essentially every programming language.
This explainer covers what JSON actually is, what data-driven design is, what belongs in a JSON file, where JSON costs you (and when to reach for a binary format), how the major engines use it, and the one confusion to avoid — that JSON the format and data-driven the architecture are not the same thing. If you want the engine-by-engine ranking, the data-driven engines comparison picks up where this leaves off.
What JSON actually is
JSON — JavaScript Object Notation — is a plain-text format for storing structured data as nested objects and arrays. It was extracted from JavaScript's object-literal syntax in the early 2000s and standardized as ECMA-404 and RFC 8259, but it has nothing to do with JavaScript at runtime: every major language ships a JSON parser. A weapon entry looks like this:
{
"id": "iron_sword",
"name": "Iron Sword",
"damage": 50,
"weight": 3.5,
"tags": ["melee", "metal"]
}
Two technical points matter, and they explain both why teams reach for JSON and why they eventually move off it.
- It is text, not binary. Every value is human-readable characters. You can open the file, read it, and edit it by hand. The cost is size and speed: the same data takes more bytes than a binary encoding and takes longer to parse.
- It is schema-free. JSON defines syntax (braces, brackets, quotes), not meaning. Nothing in the format enforces that
damageis a number or that every weapon has aname. That flexibility is freeing early and dangerous late, which is where validation and versioning come in.
The idea that makes it powerful: data-driven design
Everything useful about JSON in games comes from one architectural choice: keep the data out of the code.
Without data-driven design, your game's specifics live in source: a hardcoded int swordDamage = 50;, a level baked into the executable, a line of dialog inside a function. To change any of it, a programmer edits code, recompiles, and ships a new build. With data-driven design, the code becomes generic — a single Item class that loads its damage, weight, and tags from a file — and the specifics live in data the engine reads at runtime. Changing the sword's damage is now a one-line edit in items.json, no recompile.
The payoff is concrete.
- Designers work without engineers. Balancing, copy, and level layout move out of the programming queue and into a file a non-programmer can edit.
- Iteration gets fast. Edit the data, reload, see the change. No build step in the loop.
- One codebase, lots of content. A hundred levels become a hundred data files read by one loader, not a hundred branches of code.
- Modding and live ops open up. If the game's content is data, players can mod it and you can tune it after launch by shipping new data, not new binaries.
What belongs in JSON
In a data-driven project, almost anything that is content rather than behavior is a candidate for a data file.
| Data type | Example | Why it fits |
|---|---|---|
| Item, enemy, and character stats | HP, damage, drop rates | Tuned constantly; wants hand-editing |
| Levels and maps | Tile layouts, entity placements | Large, authored by designers; tools like LDtk export them as JSON |
| Dialog and localization | Strings keyed by ID | One file per language; translated without touching code |
| Configuration and balancing | Difficulty curves, economy rates | Numbers that change during playtesting |
| Save files | Player progress, inventory | Written and read at runtime; text aids debugging |
| Asset manifests and build data | What to load, and in what order | Drives the pipeline; easy to diff |
Not everything belongs here. Tight inner loops — the per-frame update of thousands of particles — want data laid out for the CPU cache, not parsed from text. That is a different concern, covered below.
Why JSON specifically — and where it costs you
JSON earned its place by being readable, universal, and diff-friendly. But its weaknesses are real, and mature engines treat JSON as one option in a toolbox rather than a default.
The honest costs:
- Size. Text is verbose. A number stored as
"damage": 50is several bytes; in a binary format it can be one or two. - Parse cost. Reading and validating text on every load is slower than reading binary. For a config file loaded once, irrelevant. For a level streamed mid-game, it can matter.
- No type safety. Because JSON is schema-free, a misspelled key or a wrong type fails at runtime, not at compile time.
- Schema drift. When you change the data's shape, old files break unless you version and migrate them.
When size or speed start to bite, engines pair or replace JSON with binary formats, each trading readability for performance.
| Format | What it is | Where it wins |
|---|---|---|
| JSON | Plain text, schema-free | Readability, tooling, version-control diffs |
| MessagePack / CBOR | A binary JSON — same model, compact bytes | A drop-in shrink with JSON-like flexibility |
| Protocol Buffers | Binary, schema-first (.proto plus code generation) | Smallest payloads, type safety, network protocols |
| FlatBuffers | Binary, zero-copy (built at Google for games) | Read fields without parsing the whole buffer; lowest CPU |
The pattern in the wild is to author and edit in text (JSON), then cook to binary for shipping. You keep JSON's readability during development and binary's speed in the player's hands.
How the major engines use it
Each engine expresses data-driven design in its own format — JSON is common but far from universal.
| Engine | Data format | What is data-driven |
|---|---|---|
| GDevelop | The whole project is one JSON file (game.json) | Everything — objects, events, scenes — is data |
| GameMaker | .yyp project file is JSON; rooms and objects are JSON resources | Scenes and object definitions |
| RPG Maker MV/MZ | Database stored as separate JSON files (Actors.json, Items.json, …) | The entire game — stats, skills, enemies — is a JSON database |
| Unity | JsonUtility plus ScriptableObjects | You design your own data-driven asset pipeline |
| Godot | Human-readable text resources (.tres, .tscn), plus a JSON class | Resources and scenes are text; not JSON, but the same idea |
| MonoGame | None built in — you bring a library such as System.Text.Json | Code-first framework; the data model is entirely yours |
Two honest notes. Godot is data-driven through and through, but its native format is its own text syntax, not JSON — JSON is available as an option. Construct stores its event sheets and layouts as XML inside a .c3p archive, so it is data-driven without being JSON-driven. The lesson: data-driven design is the idea; JSON, XML, and text resources are all ways to carry it.
Common mistakes
| Mistake | What goes wrong | What to do instead |
|---|---|---|
| Hardcoding values that change often | Every balance tweak needs a programmer and a recompile | Move tuned numbers into a JSON data file |
| Trusting unvalidated JSON | A bad field type or a missing key crashes the game at runtime | Validate against a schema; fail loudly in development |
| No schema versioning | A format change silently breaks old save files or mods | Version your data and write a migration path |
| Parsing JSON in a hot loop | Reparsing text every frame tanks performance | Parse once into objects; for bulk data, use a binary format |
| Confusing JSON with data-driven design | You pick a format instead of separating data from code | Decide data-vs-code first; then choose JSON or binary to carry the data |
How Egmatic fits
Egmatic is built around data-driven design at the architectural level. It separates cleanly into two parts: an editor that authors the game and a runtime engine that plays it, and the only thing that crosses that boundary is a versioned JSON contract. The editor produces JSON game data; the engine consumes it. There is no shared code between them — only the data.
That is data-driven design taken to its conclusion: the game is the data, the editor is the tool that shapes it, and the engine is the interpreter that runs it. Egmatic sits on the MonoGame runtime, which by itself is a code-first framework with no built-in data model — exactly the gap a data-driven editor fills. For the practical question of how the major engines rank on this axis, the data-driven engines comparison lays them out, and the scene graph explainer shows how the data that describes a world gets organized once the engine loads it.
Conclusion
JSON in game development is the practice of carrying your game's content as structured text the engine reads at runtime, which is the concrete form of data-driven design — keeping data out of code so designers can change the game without engineers rebuilding it. JSON wins on readability, universality, and version-control friendliness, which is why so many engines and tools use it: GDevelop's project file, RPG Maker's database, GameMaker's resources, Unity's JsonUtility, and level editors like LDtk. Its costs are size, parse speed, and the lack of a built-in schema, which is why performance-sensitive work moves to binary formats like FlatBuffers, Protocol Buffers, or MessagePack — often after authoring in text.
The one thing to hold onto is the distinction: JSON is a format; data-driven design is an architecture. You can be data-driven with XML, with text resources, or with binary — JSON is simply the most popular carrier. Separate your data from your code first; choose the format second.
Sources
- JSON specification — a lightweight, language-independent, human-readable text data format — RFC 8259: The JSON Data Interchange Syntax
- Data-driven design — separating gameplay content and parameters from code so the engine interprets data at runtime — Wikipedia: Data-driven programming
- GDevelop — the entire project saved as a single JSON file — GDevelop wiki: Project manager
- GameMaker project format — the
.yypfile stores the project as JSON — GameMaker Manual: Project format - RPG Maker MV/MZ database — actors, items, enemies, and skills stored as separate JSON files in the
data/folder — RPG Maker Wiki: Database - Unity ScriptableObjects and JsonUtility — data-driven asset design and JSON serialization — Unity Manual: JSON Serialization
- Godot resources —
.tresand.tscnare human-readable text formats preferred for version control — Godot docs: TSCN file format - LDtk — a modern open-source 2D level editor that saves levels in a pure JSON format — LDtk JSON documentation
- FlatBuffers — a binary serialization library created for game development, with zero-copy reads — FlatBuffers documentation
Related Posts
Why Your 2D Game Engine Choice Makes or Breaks Success
Your 2D game engine sets five things in concrete — the performance ceiling, the platforms you can export to, the asset pipeline, the learning curve, and how the project scales — and because every line of code and every asset is built on top of it, the wrong choice compounds until switching engines costs more than finishing. This guide explains why the engine choice is the hardest decision to undo, compares the main 2D engines on the dimensions that actually matter, uses the 2023 Unity pricing backlash as a real warning, and shows where a 2D-first IDE like Egmatic fits a developer who wants to avoid the switching trap.
2D Physics Setup: 8 Common Mistakes That Break Your Game
Most 2D physics problems are not bugs in the engine — they are setup mistakes. The eight that cause almost every case: feeding the engine pixel units instead of meters, running physics on a variable timestep, picking the wrong body type, leaving continuous collision off, steering the player with a rigidbody, setting solver iterations too low, writing directly to the transform, and ignoring sleeping bodies. Fix these at setup and most 'jitter', 'tunneling' and 'floaty jump' issues disappear.
Best 2D Game Frameworks Ranked by Learning Curve
The 2D game frameworks with the gentlest learning curve are Pygame and LÖVE, because Python and Lua are small, readable languages with simple APIs on top. Phaser, libGDX, and MonoGame add power and cross-platform reach at the cost of a steeper curve, and raylib in C is the most demanding of all. This guide ranks six serious 2D frameworks from easiest to hardest to learn, explains what changes as you move down the list, and is honest about the catch: a framework is a box of parts with no editor, so it only fits you if you want to program. If you do not, an engine or a 2D-first IDE like Egmatic is the shorter path to a finished game.