Googlebot now unescapes JSON-LD exactly once. Google announced the change on LinkedIn, and Search Engine Roundtable reported it on 21 August: "To bring our parser up to JSON and other standards, we changed our JSON-LD extraction and are now only applying a single pass of HTML unescaping." Markup that relied on a second pass to come out clean no longer gets one.
One pass is the entire change
Structured data rides inside a <script type="application/ld+json"> block. That block is HTML, its contents are JSON, and the two disagree about what an ampersand is. Google's extractor used to smooth over the mismatch by unescaping repeatedly until the text looked like something a person had typed.
Google's note is specific about what stops. "Practically speaking, this means that double-escaped entities (like & or ✔) will no longer be unrolled." Text escaped twice, once where it was stored and again when the page rendered, now halts halfway. The leftover entity stays inside the value, and the value is the part a crawler or an assistant reads back.
Gary Illyes of Google pointed at the specification rather than at a workaround: "If you're wondering what proper escaping is in JSON, I have good news for you! It's very, very well defined in RFC 8259, specifically section 7."
Menu text is where double escaping hides
Most of the structured data on a restaurant site is short strings of ordinary English, and plenty of them carry an ampersand. Section headings pair things up. Dish names join two ingredients with a symbol rather than a word. A cocktail list is worse.
Then there are the marks. Google's own example of an entity that no longer unrolls, ✔, is a tick — the character a menu reaches for to say vegan, or gluten-free. A page pushing those glyphs into its JSON-LD as HTML entities was already leaning on Google's tolerance, and that tolerance has been withdrawn.
Almost none of this markup is typed by hand. It comes out of a template, a plugin or a menu tool, which makes double escaping a property of the pipeline rather than of any one dish. A system that escapes once too often does it to the whole menu at once.
The fix Google names is a JSON escape, not an HTML one
The instruction in Google's post is to "update your code to standard JSON escapes or Unicode hexadecimal escapes (like \u0026)". An ampersand inside a JSON string can be a literal &, or it can be \u0026. What it should not be is &, and it certainly should not be &amp;, which is what a pipeline that escapes twice produces.
Where the markup comes from a menu platform rather than a hand-edited template — the case for anything running on GMMO or its competitors — the escaping is the platform's to get right. That is worth an email to find out.
Nothing reports this failure loudly
Google reads JSON-LD to pull out entity details — product prices, review stars, recipe ingredients and FAQs, in Search Engine Roundtable's list — and turns them into rich results. A menu item is the same shape of object: a name, a price, a description, a dietary flag.
A dish name arriving as Fish & Chips is still a valid string. The block parses. The type is right. The name is wrong, in a way that surfaces only if someone reads the extracted value rather than checking whether extraction happened at all.
Checking takes a few minutes. View source on a menu page, find the ld+json block, and read the dish names as they appear inside it. An entity where a character should be means the pipeline is escaping twice, and Google has stopped covering for that.
