PRACTICAL JSON-LD DEBUGGING

Why malformed JSON-LD can look like missing JSON-LD

A safer mental model for structured-data inspection

A page can contain a JSON-LD script and still be reported as having “no JSON-LD.” The usual cause is not detection—it is a parser that silently discards the block after JSON.parse fails.

The parse-and-discard trap

A common implementation finds every <script type="application/ld+json">, parses each text value, and retains only successful results. This looks compact:

const schemas = scripts
  .map(script => {
    try {
      return JSON.parse(script.textContent || "");
    } catch {
      return null;
    }
  })
  .filter(Boolean);

The final array is empty when every block is malformed. If the interface uses that array to decide whether structured data exists, a syntax problem becomes a false “not found” result.

Detection, parsing, and validation are separate states

A reliable inspector treats these as three different questions:

  1. Detection: Is a JSON-LD script present in the document?
  2. Parsing: Is its text valid JSON, and where does parsing fail?
  3. Validation: Does the parsed value follow the expected Schema.org or platform structure?

Skipping directly from detection to validated entities removes the evidence needed to answer the second question.

A source-preserving data model

Keep one record for every script before parsing it. Attach either a parsed value or a parse error, never replace the source:

{
  blockIndex: 1,
  raw: "{ \"@type\": \"Product\", ... }",
  parsed: undefined,
  parseError: {
    line: 7,
    column: 5,
    excerpt: "    \"priceCurrency\": \"USD\"",
    pointer: "    ^"
  }
}

Once parsing succeeds, normalize top-level arrays and @graph entries into inspection items while retaining their block index and JSONPath. The same mapping should also apply to nested typed entities such as an Offer inside a Product.

A five-minute debugging workflow

  1. Confirm the script exists in the rendered DOM, not only in the original HTML response.
  2. Copy the exact raw text and inspect the reported line and column.
  3. Fix JSON syntax first: commas, quotes, escaping, and truncated output.
  4. After parsing succeeds, inspect Schema.org structure and platform-specific requirements.
  5. Run the live URL through an official validator before shipping.
Dynamic pages need another pass. Client-side frameworks and tag managers can insert or replace JSON-LD after initial load. Keep the inspector open, observe script mutations, and provide an explicit rescan action.
JSON-LD Checker keeps invalid blocks, shows the exact syntax location, and lets you copy or download the original source. Try it in Chrome →
中文摘要

为什么错误的 JSON-LD 会被普通检查器显示为“不存在”

常见实现会先寻找所有 JSON-LD 脚本,再对每个代码块调用 JSON.parse,最后过滤解析失败的结果。如果所有代码块都包含语法错误,过滤后的数组就是空数组,界面便会错误地显示“未检测到 JSON-LD”。

正确做法是把三个状态分开:页面是否存在代码块、代码块能否解析、解析后的实体是否符合 Schema.org 或平台要求。每个原始代码块都应在解析前被保存;解析失败时记录准确行号、列号、上下文和源码,而不是丢弃它。

解析成功后,还要识别顶层数组、@graph 与嵌套的带类型实体,并保留它们和原始代码块的对应关系。对于 React、Vue、Tag Manager 等动态注入的场景,还需要监听 JSON-LD 脚本变化,并提供明确的手动重新扫描。