Objects, Maps, and Tables

An array answers "give me item number 3". But most real data is not naturally numbered. A player has a name, a score, and a rank; a request has a URL and a method. What you want is to file values under meaningful names and get them back by name. Every language provides exactly that structure, and almost every language calls it something different.

Think of a contact card. One card, several labelled fields: name, phone, email. You never ask a card for "field number 2", you ask for the phone. A key-value structure is a contact card the program can read, update, and extend with new labelled fields while it runs. And a list of such cards, an array of objects, is how almost all real-world data ends up shaped.

One idea, many names

  • Lua calls it a table, and builds nearly the entire language out of it.
  • JavaScript calls it an object; JSON, the data format the web runs on, is literally this structure written down.
  • Python calls it a dict, Ruby a hash, PHP an associative array.
  • Go and Java split the idea in two: a struct or class for fixed, known-in-advance fields, and a map for keys that appear at runtime.

The operations are the same everywhere: create with some initial pairs, read a value by key, update it in place, add a brand new key later, and nest structures inside each other to model anything at all. Watch each of those in the switcher below.

The Go pane is the interesting outlier: a struct declares its fields up front and no new keys can appear at runtime. That is a deliberate trade of flexibility for compile-time safety and speed, the same static-versus-dynamic split you met with types earlier in this level.

Keys are names, and names leak

Here is what this lesson contributes to the protection story. The keys in these structures are strings with meaning: score, licenseKey, isAdmin, expiresAt. A config table read out of shipped code is practically a design document. Keys leak intent exactly the way variable names do, with one crucial difference: they are often harder to rename safely.

Why harder? A local variable's every use is visible to a tool that understands scope, so renaming it is mechanical. But a key can be reached dynamically: code can build the string "isAdmin" at runtime, receive it over the network, or read it from JSON, and then use it to index the structure. A renamer that changes the key at creation but misses a dynamic lookup does not produce an error at transform time. It produces a program that quietly reads an empty slot at runtime. Safe tools are therefore conservative: when they cannot prove they see every access to a key, they leave that key alone.

This is a first taste of the deepest constraint in this whole field: a transform is only usable if it is provably behaviour-preserving, and dynamic language features shrink what is provable. Lua and JavaScript let any expression compute a key, so aggressive key renaming there needs whole-program analysis or runtime mapping tricks. It is also a two-way street: the same dynamism that blocks renaming blocks attackers' automated tools, which must be equally careful not to break the program they are trying to clean. Level 4 formalises this as the safety problem of every transformation.

Try the shape

The teaching playground has no tables, so the program below fakes one field per variable, using a naming convention to group them. Run it, and notice what the convention cannot do: nothing stops a typo like player_socre from silently creating a brand new variable instead of updating the score.

Key-value structures file data under readable names, and every language ships one: table, object, dict, hash, map, struct. The keys document your data model to anyone holding the file, and unlike variable names, they can only be safely renamed when a tool can see every access.

Frequently asked questions

Is JSON the same thing as these structures?

JSON is the written-down form of exactly this idea: key-value pairs and arrays, nested. Programs parse JSON text into their native structure, a dict in Python, an object in JavaScript, a table in Lua, work on it, and write it back out. That is why the same API can feed programs in every language.

When should I use an array versus an object or map?

Ask how you will look things up. If by position or in order, many of the same kind, use an array. If by name, one each of differently-shaped fields, use a key-value structure. The most common real-world shape is both at once: an array of records, like a list of players each with name and score.

Keep learning

  • Arrays and Lists
  • Classes and Methods
  • String Obfuscation: Hiding the Text Attackers Search First
  • Identifier Renaming: The First Layer, Never the Last
  • Lua Obfuscator
  • JavaScript Obfuscator
  • Python Obfuscator

All lessons