TL;DR
JSON Whisperer is a framework that teaches LLMs to edit JSON with diff patches (RFC 6902) instead of regenerating the entire document. The model outputs only the change operations (add, remove, replace) rather than rewriting the whole file from scratch. A standard algorithm then applies those patches to the original → you get the updated JSON.
When generating patches, LLMs run into two problems. The first is update fragmentation: when the model produces patches piece by piece, it misses related changes. Say you rename a character across every scene of a film — the model updates some mentions and skips others. The second problem is nastier — array index arithmetic. When you delete an item from a list, every following operation has to account for the shifted indices (was [0,1,2,3] → removed 1 → now [0,1,2]). LLMs regularly trip over this math or mix up zero-based and one-based indexing.
The fix — EASE (Explicitly Addressed Sequence Encoding): arrays are converted into dictionaries with unique keys like "ax", "cd", "np". The order of items is stored separately in a key display_order: "ax,cd,np". To delete, add or move an item, you only change the display_order string. No index arithmetic, and operations can be applied in any order.
Want this for your own case? Apply this study to your task: AI adapts its method to what you are working on and writes the prompt.
Method Blueprint
Diff-based editing:
STEP 1: The LLM receives the JSON + an instruction → generates an RFC 6902 patch
STEP 2: An algorithm applies the patch to the original JSON → new JSONIt all happens in a single prompt.
EASE for lists:
BEFORE: ["Alice", "Bob", "Charlie"] // indices 0,1,2
AFTER: {
"ax": "Alice",
"cd": "Bob",
"np": "Charlie",
"display_order": "ax,cd,np"
}Operations on EASE lists:
- Remove Bob: change
display_orderto "ax,np" + delete the key "cd" - Move Charlie to the front: change
display_orderto "np,ax,cd" - Add Dave in third place: add the key "yz": "Dave", change
display_orderto "ax,cd,yz,np"
Example in Action
Task 1: Editing a job posting
Task: You have a long job posting on LinkedIn (a JSON with the description, requirements and perks). You need to update the salary, add a new requirement and reword one of the responsibilities.
Prompt:
Here is the job posting JSON:
{
"title": "Senior Python Developer",
"salary": {"from": 130000, "to": 160000, "currency": "USD"},
"requirements": ["3+ years of Python", "Django/FastAPI"],
"responsibilities": {
"main": "Building backend services",
"additional": "Code review for junior developers"
}
}
Instruction:
1. Raise the upper salary bound to 180000
2. Add the requirement "Experience with PostgreSQL"
3. Change the main responsibility to "Building and optimizing backend services"
Generate an RFC 6902 patch for these changes.Result: The model returns a patch of 3-4 operations:
replacefor/salary/toaddfor a new item in/requirementsreplacefor/responsibilities/main
Instead of regenerating the whole JSON (hundreds of tokens), you get just surgical operations (dozens of tokens).
Task 2: Managing a speaker lineup with EASE
Task: You're organizing an AI conference in Chicago. The speaker list keeps changing — someone cancels, the order shifts, new people get added.
Prompt:
Here is the conference speaker list in EASE format:
{
"speakers": {
"rt": {"name": "Ethan Brooks", "topic": "AI in media"},
"np": {"name": "Daniel Miller", "topic": "LLMs for business"},
"xy": {"name": "Maria Lopez", "topic": "AI ethics"}
},
"display_order": "rt,np,xy"
}
Instruction:
1. Daniel Miller has canceled his talk — remove him
2. Add a new speaker: Sam Carter, topic "Prompting in practice"
3. Put Sam second in the lineup
Generate an RFC 6902 patch.Result: The model creates a patch that:
- Adds the new speaker under the key "ab":
{"name": "Sam Carter", "topic": "Prompting in practice"} - Updates
display_orderto "rt,ab,xy" (Carter is now second, Miller is gone) - Deletes the key "np" from the dictionary
Without EASE the model would get tangled up: "Miller was second (index 1), so after deleting him Lopez is second? Or not? Where do I insert Carter — index 1 or 2?"
With EASE the model simply writes the new key sequence: "rt,ab,xy". No index counting at all.
Why It Works
Problem 1: Index arithmetic
LLMs generate text left to right, token by token. They don't "do math in their head" — they continue a pattern. When the model has to track how indices change after a remove in the middle of a list, it loses the thread. This isn't math, it's state tracking across many steps, which is hard for autoregressive generation.
Where LLMs shine: patterns and structure Models are great with key-value pairs, because that's a rock-solid pattern in their training data. JSON objects with keys are everywhere. A sequence of keys in a string ("ax,cd,np") is a familiar pattern too (CSV, comma-separated lists).
How EASE plays to the LLM's strengths: Instead of asking "recalculate the indices," we say "rewrite the key sequence." The end result is the same operation, but the model does what it's good at — working with text patterns, not arithmetic.
Problem 2: Update fragmentation This is solved with few-shot learning on synthetic examples. The researchers automatically generate triples (JSON + instruction + correct patch) using a strong model (Claude 3.5 Sonnet). These examples show the model how to make comprehensive updates without missing related changes. DSPy optimizes the selection of the best examples from the dataset.
Control knobs:
- Number of few-shot examples → more examples = better grasp of the patterns, but more expensive in tokens
- Synthetic vs. real examples → synthetic ones are easy to generate, real ones reflect your tasks more accurately
- Patch format → RFC 6902 is the standard, but you can adapt it to your own format
- EASE vs. standard indices → EASE for complex lists, standard for simple ones
Prompt Template
Basic diff patch without EASE
You are a structured data editor.
You are given a JSON object and an instruction for changing it. Your job is to generate an **RFC 6902 patch** (a minimal set of operations), not to rewrite the whole JSON.
**Rules:**
- Use only these operations: add, remove, replace
- Write paths with slashes: /field/subfield
- Array indices start at 0: /items/0
- Change ONLY what the instruction asks for
- Watch for related changes (e.g., if you change a name in one place, check the others)
**Input:**
JSON: {json_document}
Instruction: {edit_instruction}
**Output format:**
Explain step by step what needs to change (1-2 sentences).
Then output the array of operations in this format:
[
{"op": "replace", "path": "/field", "value": "new_value"},
{"op": "add", "path": "/items/-", "value": {...}}
]Fill in:
{json_document}— the source JSON{edit_instruction}— what to change (in plain English)
EASE patch for lists
You are a structured data editor with an advanced technique for handling lists.
**EASE (Explicitly Addressed Sequence Encoding):**
Lists in the JSON are represented as dictionaries with unique keys (two letters: "ax", "cd", "np").
The order of items is stored in the "display_order" key as a string: "ax,cd,np"
**Operations on EASE lists:**
1. **Add an item:**
- Create a new key (2 random letters, e.g. "rt")
- Insert it into display_order at the right position
Example: "ax,cd,np" → "ax,rt,cd,np" (inserted between ax and cd)
2. **Remove an item:**
- Take the key out of display_order
- Delete the key itself from the dictionary
Example: "ax,cd,np" → "ax,np" (removed cd)
3. **Move an item:**
- Reorder the keys in display_order
Example: "ax,cd,np" → "np,ax,cd" (np is now first)
**Input:**
JSON with EASE lists: {json_document}
Instruction: {edit_instruction}
**Output format:**
Explain what you're doing (1-2 sentences).
Output the RFC 6902 patch:
[
{"op": "replace", "path": "/items/display_order", "value": "new_sequence"},
{"op": "add", "path": "/items/new_key", "value": {...}},
{"op": "remove", "path": "/items/old_key"}
]Fill in:
{json_document}— JSON with lists in EASE format{edit_instruction}— the list operations
🚀 Quick start — paste into the chat:
Here's the JSON Whisperer template. Adapt it to my task: [your JSON task].
Ask me questions to fill in the fields.
[paste one of the templates above]The LLM will ask:
- What does your JSON document look like?
- What needs to change?
- Are there lists that change often? (for EASE)
The model will take the pattern from the template and adapt it to your data structure.
Limitations
⚠️ Synthetic data: The study was trained and tested on automatically generated examples. Real-world editing scenarios may contain patterns that never showed up in the synthetic set.
⚠️ Input token overhead: Few-shot examples inflate the input context. For very large JSON (thousands of lines) this can eat up the savings on output tokens and bump into the context window limit. The fix is fine-tuning the model so it doesn't need few-shot examples.
⚠️ Not for trivial edits: If you need to change one field in a small JSON, it's easier to just ask for the whole file to be rewritten. Patches pay off when the document is large or there are several changes.
⚠️ EASE requires a conversion step: Standard JSON arrays have to be converted into EASE format. For one-off tasks that's overhead; for recurring ones it pays for itself.
How They Tested It
A team from Lightricks (the company behind AI tools for creators) tested the approach on real production tasks: editing scenes in an AI filmmaking platform. Each scene is a JSON with metadata (weather, location, voiceover) and an array of shots, where every shot is a nested object with a type, an action and details.
They generated 400 editing examples with Claude Sonnet and split them into 4 difficulty types:
- Simple — a single field ("change the weather to cloudy")
- Creative — generating new content ("add one more shot")
- Complex — interlinked changes ("change the scene so that Melody's ex is in the audience and she spots him halfway through her performance")
- List Manipulation — list operations ("delete every third shot")
They compared three approaches:
- Full regeneration (baseline) — the model rewrites the entire JSON
- Standard diff patches — RFC 6902 with regular array indexing
- EASE diff patches — RFC 6902 + EASE encoding for lists
They tested two models of different scale: GPT-4o-mini (8B parameters) and Claude Sonnet (175B). For each one: zero-shot and few-shot with DSPy-optimized examples.
Evaluation metrics:
- F1 on patch structure — do the operations match (
op,path), without checking thevaluecontents - Semantic accuracy — an LLM-as-a-judge scores how meaningful the changes are
- Success rate — the share of patches that applied without errors (no syntax errors, no nonexistent paths)
The size of the effect was the surprise:
- EASE beat standard indexing on every task type, especially Complex and List Manipulation
- Few-shot learning on synthetic data produced a sharp jump in accuracy — even standard indexing with few-shot beat zero-shot across the board
- The biggest surprise: the small GPT-4o-mini with EASE and few-shot matched the big Claude Sonnet doing full regeneration, while saving 31% of tokens
The practical takeaway: the right prompting + data structure matter more than model size. EASE turns a hard task (index arithmetic) into an easy one (rewrite a string), letting even small models perform like giants. For businesses, that means you can use cheaper models without losing quality.
Original from the Paper
Standard List Indexing Prompt
You are a helpful movie production assistant, integrated inside a generative AI video app.
You are a master of your craft, and confident with your choices. You know perfectly well
how to edit a scene and cast characters.
Given an input json representing an object in a short film and a user command,
your job is to return the json-patches needed to be made on the input json in order
to edit it fully and hermetically according to the command.
Try to understand the users desired result
Make as many updates as possible, in order to fully and hermetically follow the
edit command.
Your Jsons need to be sensitive in terms where it is not changing things that
shouldn't be changed, and changing things that need to be changed, including their
implications, for example:
- If the director commands you to add a shot to the scene - Be creative enough to
make a shot with a description that suits the scene, while not changing the rest
of the shots in the scene.
Output Fields:
- rationale: one line string start with 'let's think step by step, we need to...'
explain the problem and how you are going to solve it
- json_diff_patch: json-patches (RFC 6902) needed to be made on the input json in
order for the json to match the command, all lists indices are always 0 based.
- is_unsupported: True if the command is unrelated to the json or the updated json
schema is different from the input json, otherwise FalseContext: This is the prompt for the standard approach with numeric indices. The model has to keep track of index changes on its own during list operations.
EASE Encoding Prompt
A sub json contains a "list_display_order" is an ordered dict,
list_display_order determines the item order, not the dictionary order.
Keys are random two-letter strings (e.g., xy), with no inherent order.
Every item is accessed by its key, and the order is determined by the list_display_order.
To add, remove or move items, you must update list_display_order as a single string,
for example:
given a dictionary:
list_display_order: "xk,xy,np,cv"
moving the second item to the first place, and the last item to the second place
will result:
list_display_order: "xy,cv,xk,np"
Adding a new item without any specific ordering will add the item as the last,
result updating the list_display_order as:
list_display_order: "xy,cv,xk,np,rt"
and adding the item with random key "rt" to the dictionary.
Removing the first item will result updating the list_display_order as:
list_display_order: "cv,rt,xk,np"
and removing the item with key "xy" from the dictionary.
In any case existing mapping between keys and values should be kept.Context: The core of the EASE prompt — it explains to the model how to work with ordered dictionaries via display_order. Note that the authors give concrete examples of operations — that's critical for the model to get it right.
Adaptations
Technique: EASE for any list in your prompts
The EASE principle is universal — you can use it anywhere an LLM handles lists through a prompt, not just in JSON.
Example: managing a project task list
Instead of a regular list:
Sprint tasks:
1. Fix the login bug
2. Add PDF export
3. Optimize database queries
4. Write the API documentationUse the EASE format:
Sprint tasks:
{
"ax": "Fix the login bug",
"cd": "Add PDF export",
"np": "Optimize database queries",
"rt": "Write the API documentation",
"order": "ax,cd,np,rt"
}
When the list needs to change, only edit "order" and add/remove keys.Why it works:
- The model doesn't get confused by "delete task 2" → "so is task 3 now task 2?"
- You can say "move task 'np' to the top" — zero ambiguity
- Multiple operations apply without conflicts
Where to use it:
- Lists in long-running conversations (the model "remembers" via EASE and doesn't mix up the numbers)
- Collaborative filtering tasks (ranking, sorting)
- Any dynamic list whose order changes often
Adaptation: EASE for working with large documents
Task: You have long lecture notes (10+ pages of markdown). You need to reorder sections, add new ones and delete outdated ones. The usual approach — the LLM regenerates the whole document = thousands of tokens + the risk of losing details.
Solution:
Here is the structure of the notes in EASE:
{
"sections": {
"ax": "# Introduction\n[introduction text...]",
"cd": "# Core Concepts\n[text...]",
"np": "# Use Cases\n[text...]",
"rt": "# Conclusion\n[text...]"
},
"display_order": "ax,cd,np,rt"
}
Instruction:
1. Add a "Common Mistakes" section between "Use Cases" and "Conclusion"
2. Move "Core Concepts" to the end (right before the conclusion)
Generate an RFC 6902 patch for these changes.The model will return:
[
{"op": "add", "path": "/sections/yz", "value": "# Common Mistakes\n..."},
{"op": "replace", "path": "/display_order", "value": "ax,np,yz,cd,rt"}
]Advantages:
- The text isn't regenerated — only the structure is
- Sections stay untouched (the LLM doesn't rewrite them "in its own words")
- Token savings on long documents
Resources
JSON Whisperer: Efficient JSON Editing with LLMs
- Dataset and code: https://github.com/emnlp2025/JSON-Whisperer/
- RFC 6902 JSON Patch: https://datatracker.ietf.org/doc/html/rfc6902
- jsondiffpatch library: https://github.com/benjamine/jsondiffpatch
Authors: Sarel Duanis, Asnat Greenstein-Messica, Eliya Habba
Affiliations: Lightricks, The Hebrew University of Jerusalem