Google zmienia sposób parsowania JSON-LD
Google zmienił sposób ekstrakcji danych JSON-LD. Parser stosuje teraz tylko jedno przejście dekodowania HTML zamiast kilku. W praktyce oznacza to, że podwójnie zakodowane encje HTML czyli specjalne znaki nie będą dekodowane to zamierzonego znaku. Jeśli strona podwójnie escapuje treść trafiającą do JSON-LD, to Google od teraz odczyta ją błędnie.

Google Search Central opublikowało informację:
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. Practically speaking, this means that double-escaped entities (like & or ✔) will no longer be unrolled.
If you’re using JSON-LD for structured data, be sure to update your code to standard JSON escapes or Unicode hexadecimal escapes (like \u0026).
Czyli w skrócie:
- Wcześniej parser Google wykonywał więcej niż jedno przejście dekodowania HTML na treści wyciąganej z bloków JSON-LD
- Od teraz wykonuje dokładnie jedno przejście
- Google rekomenduje, żeby nie polegać na tym mechanizmie w ogóle i stosować standardowe escape’y JSON lub Unicode (
\u0026).
To zmiana w tym jak Google interpretuje treść, którą dostaje jako dane strukturalne.

Jak to teraz działa
Google podaje dwa przykłady problematycznych zapisów.
Przykład 1: &
- Zapis w kodzie źródłowym:
& - Jedno przejście dekodowania HTML zamienia
&na&, więc&staje się& - Wynik koncowy to
&– czyli NIE znak docelowy&
Przykład 2: ✔
- Zapis w kodzie źródłowym:
✔ - Po jednym przejściu:
✔ - Wynik końcowy to
✔– czyli NIE docelowy znak checkmark (✔)
W obu przypadkach wynikiem końcowym jest tekst, który dalej zawiera fragment encji HTML zamiast właściwego znaku. Wcześniej Google dekodował to wielokrotnie, aż dochodził do prawidłowego wyniku. Teraz zatrzymuje się po pierwszym kroku.
Dlaczego to w ogóle jest problem i skąd się bierze
Podwójne escapowanie najczęściej powstaje wtedy, gdy ten sam mechanizm szablonu lub CMS’a, który automatycznie zamienia znaki specjalne na encje HTML w artykule (np. & -> &) jest używany do wygenerowania treści wewnątrz bloku application/ld+json.
Typowy scenariusz:
- Redaktor wpisuje w CMS’ie:
Research & Development - CMS zapisuje to w bazie danych już jako
Research & Development, bo tak escapuje pola tekstowe - Wygenerowany blok JSON-LD dodatkowo escapuje tę wartość przy wstawianiu do HTML, tworząc
Research & Development - Do niedawna Google to „naprawiał” po swojej stronie. Teraz nie naprawia.
Strona mogła więc w wyszukiwarce mogła wyglądać prawidłowo przez lata, mimo błędu w kodzie. Błąd był maskowany przez zachowanie parsera Google.
Podstawa standardu RFC 8259
Zmiana Google, to po prostu dostosowanie do specyfikacji JSON. Dokładnie RFC 8259, sekcja 72
„All Unicode characters may be placed within the quotation marks, except for the characters that MUST be escaped: quotation mark, reverse solidus, and the control characters (U+0000 through U+001F).
Any character may be escaped (…) as a six-character sequence: a reverse solidus, followed by the lowercase letter u, followed by four hexadecimal digits (…) Alternatively, there are two-character sequence escape representations of some popular characters.”
Dwa fakty z tego zapisu maja bezpośrednie znaczenie dla SEO:
- Znak
&nie wymaga escapowania w JSON. Może wystąpić w stringu bez żadnego dodatkowego zapisu - Jedyne dopuszczalne mechanizmy escapowania w JSON to sekwencja
\uXXXX(cztery cyfry szesnastkowe) oraz krótkie dwuznakowe sekwencje typu\\czy\". Encje HTML (&,✔itd.) nie są częścią specyfikacji JSON
Pojedyncze przejście dekodowania HTML, które Google nadal wykonuje nie jest zachowaniem zdefiniowane przez RFC 8259. Parser JSON zgodny z RFC 8259 interpretowałby & ciąg znaków typu: &, a, m, p, ;. Także zmiana Google to redukcja liczby przejść z „kilku” do „jednego” – krok w stronę zgodności, a nie pełna zgodność ze standardem.
Checklista do sprawdzenia
- Audyt JSON-LD na typach stron (produkty, artykuły, strona główna z danymi organizacji, strony lokalizacji) pod kątem podwójnie zakodowanych encji HTML
- Kod – sprawdź czy funkcja generująca blok JSON-LD używa dedykowanej serializacji JSON (np.
json_encodew PHP,JSON.stringifyw JS) albo czy przechodzi dodatkowo przez funkcję escapującą HTML - Naprawa u źródła – docelowy zapis w kodzie powinien zawierać znak escape Unicode (
\u0026), anigdy encję HTML - Przetestuj strony Rich Results Test lub walidator schema.org po wdrożeniu poprawki, korzystając z faktycznie wyrenderowanego kodu strony. Możesz tez użyć mojego skanera żeby zautomatyzować cały proces.
Automatyczny audyt: skaner JSON-LD Escape
Checklistę da się przejść ręcznie dla kilkunastu adresów ale przy większych stronach warto automatyzować proces. Weź mój skaner i odpal lokalnie.
Funkcje skanera:
- pobiera sitemapy i indeksy sitemap
- skanuje strony równolegle i analizuje każdy blok
<script type="application/ld+json">, - wykrywa wszystkie formy z macierzy poniższych testów
- możliwość eksportu wyników do CSV z numerem bloku i snippetem – gotowe do przekazania developerowi
⚠️ Uwaga:
- Nie wystawiać publicznie (online)! Narzędzie przeznaczone do użytku na localhost (np. XAMPP) ze względu na brak zabezpieczeń.
Kod na GitHub: Skaner JSON-LD Escape
8 testów, 4 strony, 2 narzędzia
Zrobiłem 4 strony i przeprowadziłem 8 testów używając:
- Test wyników rozszerzonych (Rich Results Test)
- Walidator Schema
Test 1: brak escapowania
A & B → A & B
Znak & w JSON nie wymaga escapowania (RFC 8259), wiec zostaje odczytany dokładnie tak, jak został zapisany. To jest punkt odniesienia dla reszty testu.
Test 2: pojedyncze escapowanie
A & B → A & B
To potwierdza ogłoszenie Google: 1 przejście dekodowania HTML nadal działa.
Test 3: podwójne escapowanie
A &amp; B → A & B
To jest dokładne potwierdzenie ogłoszenia Google. Podwójnie zakodowana wartość nie została w pełni rozwinięta – po jednym przejściu zostało & zamiast &. To jest dokładnie ten wynik, który teraz będzie trafiał do danych strukturalnych Google i (potencjalnie) do SERP.
Test 4: macierz rożnych typów escapowania
W tym teście zrobiłem mix, bo sprawdzam encje nazwane, dziesiętne i szesnastkowe
| Wejście | Wynik | Interpretacja |
|---|---|---|
A & B | A & B | OK – brak escapowania, brak zmian, tak ma być |
A & B | A & B | OK |
A &amp; B | A & B | POTWIERDZONE – podwójne escapowanie nie zostaje w pełni rozwinięte |
<test> | <test> | OK – 1 przejście działa dla znaków < i > |
&lt;test&gt; | <test> | POTWIERDZONE – ten sam wzorzec błędu co przy & |
"test" | "test" | OK – 1 przejście działa dla cudzysłowu |
&quot;test&quot; | "test" | POTWIERDZONE – podwójne escapowanie cudzysłowia nie działa |
A A B | A A B | OK – encja dziesiętna A (czyli kod ASCII litery A) dekodowane w 1 przejściu bez problemów |
A &#65; B | A A B | POTWIERDZONE – encja dziesiętna działa identycznie jak encje nazwane |
A A B | A A B | OK – encja szesnastkowa A (hex 41 = dec 65 = litera A) dekodowana w 1 przejściu |
A &#x41; B | A A B | POTWIERDZONE – identyczny wzorzec |
Wniosek: mechanizm „jednego przejścia” działa niezależnie od typu encji HTML, bez znaczenia czy jest:
- nazwana –
&,<,>," - dziesiętna
A - szesnastkowa –
A
Problem dotyczy całej rodziny encji HTML Google dostosował swój parser do tego jak standard RFC 8259 definiuje JSON. Czyli do tego jak powinno to wyglądać od zawsze.
FAQ
Co to są encje HTML?
Encje HTML to specjalny sposób zapisywania znaków w kodzie HTML za pomocą określonej składni. Stosuje się je przede wszystkim w przypadku znaków, które mają w HTML znaczenie specjalne oraz znaków trudnych do zapisania bezpośrednio. Encje są interpretowane przez parser HTML i zamieniane na odpowiadające im znaki.
Co to jest podwójne escapowanie?
Podwójne escapowanie to sytuacja, w której znak lub encja zostaje zakodowana więcej niż jeden raz. W efekcie zamiast docelowego znaku powstaje tekst zawierający kolejną warstwę kodowania. W przypadku JSON-LD osadzonego w HTML może to prowadzić do tego, że dane po przetworzeniu nie zostaną odkodowane w sposób zgodny z oczekiwaniami parsera.
- Google informuje o zmianie parsowania JSON-LD –
https://www.linkedin.com/posts/to-bring-our-parser-up-to-json-and-other-share-7496492350370713600-jxi2/ ↩︎ - RFC 8259, sekcja 7 – https://datatracker.ietf.org/doc/html/rfc8259#section-7 ↩︎
