Redis JSON
JSON is the format most web and mobile apps use to exchange data. Redis JSON stores a JSON document as a real structure instead of one block of text. You can read or change a single field deep inside the document without loading the whole thing.
The Filing Folder Analogy
A Hash is a single sheet of paper with a list of labeled lines. A JSON document is a folder with sheets inside, and some sheets hold smaller folders. You can open the folder, pull one sheet, change one line, and put it back without touching the rest.
Key: user:1 ┌─────────────────────────────────────────┐ │ $ (root) │ │ ├─ name: "Asha" │ │ ├─ age: 29 │ │ ├─ address: │ │ │ ├─ city: "Pune" │ │ │ └─ pin: "411001" │ │ └─ skills: ["sql", "redis"] │ └─────────────────────────────────────────┘
Paths with JSONPath
A path points to a spot inside the document. The dollar sign means the root.
Path Points To ──────────────────── ─────────────────────── $ The whole document $.name The name field $.address.city The city inside address $.skills[0] The first skill $.skills[*] Every skill
JSON.SET and JSON.GET
127.0.0.1:6379> JSON.SET user:1 $ '{"name":"Asha","age":29,"address":{"city":"Pune"},"skills":["sql","redis"]}'
OK
127.0.0.1:6379> JSON.GET user:1 $.name
"[\"Asha\"]"
127.0.0.1:6379> JSON.GET user:1 $.address.city
"[\"Pune\"]"
Path queries that start with $ always return an array of matches, so the answer wraps the name in square brackets.
Changing Parts of a Document
127.0.0.1:6379> JSON.NUMINCRBY user:1 $.age 1 "[30]" 127.0.0.1:6379> JSON.ARRAPPEND user:1 $.skills '"python"' 1) (integer) 3 127.0.0.1:6379> JSON.SET user:1 $.address.city '"Mumbai"' OK
Each command runs as one atomic step. Two servers can raise the age at the same moment, and Redis applies both changes correctly.
Removing Parts
127.0.0.1:6379> JSON.DEL user:1 $.address (integer) 1 127.0.0.1:6379> JSON.TYPE user:1 $.skills 1) "array"
Reading Several Fields at Once
JSON.GET accepts more than one path. Redis returns a single JSON object that holds one entry per path.
127.0.0.1:6379> JSON.GET user:1 $.name $.age
"{\"$.name\":[\"Asha\"],\"$.age\":[30]}"
MGET-style reads across many keys work too. JSON.MGET takes several keys and one path, which suits list pages that show one field from many documents.
127.0.0.1:6379> JSON.MGET user:1 user:2 $.name 1) "[\"Asha\"]" 2) "[\"Ravi\"]"
JSON versus Hash versus String
Feature String (text) Hash JSON ───────────────────────── ────────────── ──────────── ──────────── Nested data Text only No Yes Change one inner field Rewrite all Yes (flat) Yes (any depth) Atomic number increment No Yes Yes Works with Search index No Yes Yes Best for Simple values Flat objects Documents
Pick a Hash for flat records with simple fields. Pick JSON when the data has lists or nested objects.
Practical Example – Product Catalog
Each product lives in one JSON key.
JSON.SET product:501 $ '{"name":"Desk Lamp","price":899,"tags":["home","light"],"stock":{"pune":12,"delhi":7}}'
Sale starts:
JSON.SET product:501 $.price 749
A customer buys one lamp in Pune:
JSON.NUMINCRBY product:501 $.stock.pune -1
Add a tag:
JSON.ARRAPPEND product:501 $.tags '"gift"'
The app never downloads or rewrites the whole product.
Tips for Good JSON Design
- Keep each document a reasonable size. Giant documents slow replication and snapshots.
- Store one entity per key, such as one user or one product.
- Combine JSON with Redis Search to query fields across many documents.
- Set a TTL with EXPIRE when the document represents temporary data.
Key Points
- Redis JSON keeps documents as structured data that Redis understands.
- Paths starting with $ select any spot inside the document.
- JSON.SET, JSON.GET, JSON.DEL, JSON.NUMINCRBY, and JSON.ARRAPPEND cover daily work.
- Partial updates run atomically and avoid full rewrites.
