JSON-LD, Microdata, and RDFa are three syntaxes for the same thing: expressing schema.org vocabulary on a web page. All three expand to the same RDF triples, so a Product marked up in any of them says exactly the same thing to a consumer. The choice is therefore about where the markup lives and who maintains it, not about meaning. For most sites JSON-LD is the better default, and Google recommends it, but attribute formats still win in specific situations.
The three formats express the same triples
JSON-LD puts the data in a <script type="application/ld+json"> block, separate from the HTML. Microdata annotates existing HTML elements with itemscope, itemtype, and itemprop attributes. RDFa (in practice RDFa 1.1 Lite) annotates them with vocab, typeof, and property.
Run any of the three through a parser and the output is a set of statements: this node is of type https://schema.org/Product, its https://schema.org/name is “Field Notebook, A5”, its https://schema.org/offers points to a node of type Offer whose price is “18.00”. Nothing in that output records which syntax produced it. See triples: subject, predicate, object for the model and RDF for the wider syntax family.
Two consequences follow. First, no format is more expressive than the others for practical schema.org work, so arguments about which one search engines “prefer semantically” are misplaced. Second, because they are interchangeable, migrating between them changes nothing about what a page asserts, which makes migration low-risk.
In practice, the two HTML formats can add small differences of their own. In our six-syntax experiment, the same 66 facts about one university came back identical from JSON-LD, but Microdata and RDFa tagged every string with the page’s lang value, and Microdata turned decimals into doubles.
Comparison table
| Aspect | JSON-LD | Microdata | RDFa 1.1 Lite |
|---|---|---|---|
| Where the markup lives | One script block, usually in <head> |
Attributes on visible HTML elements | Attributes on visible HTML elements |
| Coupling to the HTML | None; data is independent of the DOM | Tight; the data is the DOM structure | Tight; the data is the DOM structure |
| Spec body and status | W3C Recommendation (1.0 in 2014, 1.1 in 2020) | Originally a WHATWG/W3C HTML spec; the W3C Microdata note is no longer actively developed | W3C Recommendation (RDFa 1.1, with RDFa Lite as a minimal subset) |
| Google support | Read and recommended | Read | Read |
| Ease of injection | High; a template partial, a tag manager, or a plugin | Low; requires editing markup around content | Low; requires editing markup around content |
| Ease of auditing | High; read one block | Moderate; trace attributes across the document | Moderate; trace attributes across the document |
| JS-rendering caveats | Client-injected blocks depend on the render pass | Same risk if the annotated HTML is client-rendered | Same risk if the annotated HTML is client-rendered |
| Duplication risk | Values can drift from visible text | Values cannot drift; they are the visible text | Values cannot drift; they are the visible text |
| Best use case | Most sites; entity graphs spanning several types | Content edited by non-developers; existing CMS templates | Publishing workflows already using RDFa; namespaces beyond schema.org |
The same fact, three ways
A minimal Product with one Offer. In JSON-LD:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Field Notebook, A5",
"offers": {
"@type": "Offer",
"price": "18.00",
"priceCurrency": "USD"
}
}
</script>
The same fact in Microdata:
<div itemscope itemtype="https://schema.org/Product">
<h1 itemprop="name">Field Notebook, A5</h1>
<div itemprop="offers" itemscope itemtype="https://schema.org/Offer">
<meta itemprop="priceCurrency" content="USD">
<span itemprop="price">18.00</span>
</div>
</div>
And in RDFa Lite:
<div vocab="https://schema.org/" typeof="Product">
<h1 property="name">Field Notebook, A5</h1>
<div property="offers" typeof="Offer">
<meta property="priceCurrency" content="USD">
<span property="price">18.00</span>
</div>
</div>
The three blocks produce identical triples. The differences are visible in the code rather than in the data: the JSON-LD block repeats the product name that also appears in the page body, while the attribute versions reuse the visible text and need <meta> elements for values a visitor never sees, such as the currency code.
Why Google recommends JSON-LD
Google Search Central states that Google Search supports JSON-LD, Microdata, and RDFa, and recommends JSON-LD. The reasoning is operational.
Markup in one block can be generated from the same data that renders the page, reviewed as a single unit, and changed without touching layout. Attribute markup is distributed through the template, so a redesign that replaces a <span> with a <div>, or moves a price outside the element carrying itemscope, can break an entity without any visible symptom. Attribute formats also make some structures awkward: an entity whose properties are scattered across distant parts of the page, or a property with no visible representation, needs empty <meta> or <link> elements to carry values.
JSON-LD also handles multi-entity graphs comfortably. A page describing an Organization, a WebSite, a WebPage, and an Article can put all four in one @graph array with @id references between them. Expressing the same graph in attributes means finding an element in the DOM to hang each node from. The syntax and keyword details are covered in JSON-LD.
When an attribute format is still the better answer
Three situations favor Microdata or RDFa.
Markup that must stay attached to content edited by non-developers. If recipe steps, event dates, or job descriptions are entered in a CMS by editors, attribute markup applied in the template guarantees the data matches what was entered. A separate JSON-LD block has to be generated from the same fields, and if that generation is missed for a field, the block goes stale while the page looks fine.
CMS templates that already emit it. Many themes, plugins, and e-commerce platforms ship with Microdata or RDFa built into their templates. Working markup that already validates has no upside to replace. Effort is better spent on properties that are missing.
Tables and lists where the visible text is the data. A specification table, a pricing table, or a schedule is a case where the HTML structure already mirrors the data structure. Annotating rows in place is often less code than serializing the same table into JSON, and it cannot drift out of sync. See Microdata and RDFa for the syntax in each case.
Migration: do not double-mark the same entity
The common failure during a migration is leaving the old markup in place while adding the new. Consumers merge all structured data found on a page, so a Product in Microdata plus a Product in JSON-LD is read as two products unless both carry the same @id or itemid. Duplicate entities produce inflated counts, contradictory values when the two sources disagree, and validator warnings that point at the wrong block.
Migrate one type at a time. Add the JSON-LD, confirm the new block parses and reports the properties expected, then remove the attributes for that type in the same release. Where the change cannot be atomic, give both representations the same identifier so they collapse into one node. Marking up different types in different formats on the same page is fine, since a Microdata BreadcrumbList and a JSON-LD Article are separate entities anyway.
How validators report each format
Both the Rich Results Test and the schema.org Schema Markup Validator parse all three formats and group results by detected item, labeling the source format. Reading those reports differs by format in practice.
For JSON-LD, an error points at a line in the block, so the fix is usually obvious. For Microdata and RDFa, an error points at a property that is missing or misplaced, and locating the cause means finding which element carries the enclosing itemscope or typeof and checking whether the property element is genuinely inside it. Nesting errors are the most common: a property that sits outside its parent’s element is attached to the wrong item, or to no item, and validators can only report the effect.
Validators also flag the duplicate-entity case, though the message describes a type appearing more than once rather than naming the format collision. Fuller coverage of each tool is in structured data testing tools and structured data.
For developers
Test the output, not the input. Parse the rendered page with a library that handles all three formats (extruct in Python, or the JSON-LD Playground plus a Microdata extractor) and assert on the resulting triples. That makes a format migration a refactor verified by tests, since the expected triples do not change.
Where markup is generated, generate it from typed objects rather than string templates, whichever format is emitted. For attribute formats that means the template reads the same object the JSON-LD serializer would; for JSON-LD it means serializing with a JSON library so escaping is handled.
For SEOs
The format is not a ranking consideration and switching formats will not, on its own, change how a page performs. What matters is whether the required properties for the target rich result are present, accurate, and consistent with the visible page. An audit that recommends migrating to JSON-LD purely for its own sake is proposing work with no measurable outcome.
The genuine SEO argument for JSON-LD is maintenance. Markup that lives in one block is easier to keep correct across redesigns, easier to extend with entity properties such as sameAs and @id, and easier to hand to a developer as a single deliverable. Those properties are where entity work happens, so a format that makes them easy to add is worth adopting for new templates. See entity SEO and sameAs schema.
Related pages
- JSON-LD
- Microdata
- RDFa
- Structured data
- schema.org
- Structured data testing tools
- One university, six syntaxes (experiment: the same facts in six formats, parsed back and compared)
FAQ
Is JSON-LD better than Microdata for SEO?
For maintenance, yes. Both produce the same triples and Google reads both, so neither carries an advantage in meaning. JSON-LD keeps the data in one block that can be generated, reviewed, and changed without touching the HTML, which is why Google recommends it. Microdata remains a reasonable choice when markup should stay attached to editor-entered content.
Does Google still support Microdata and RDFa?
Yes. Google Search Central lists JSON-LD, Microdata, and RDFa as the supported structured data formats, and states that JSON-LD is recommended. Existing Microdata or RDFa that validates and includes the required properties does not need to be replaced to be eligible for rich results.
Can I use JSON-LD and Microdata on the same page?
Yes, and it is safe as long as the two formats describe different entities. Marking up the same entity twice creates duplicates, because consumers merge everything found on the page. If both must exist during a migration, give both representations the same identifier so they resolve to one node.
Which structured data format should a new site use?
JSON-LD, in almost all cases. It is a W3C Recommendation, Google recommends it, it can be generated from page data server-side, and one block can describe several linked entities with @id references. The exception is a CMS or theme that already emits valid Microdata, where the working markup is worth keeping.
Sources and further reading
- Google Search Central, Introduction to structured data markup: https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data
- W3C, JSON-LD 1.1: https://www.w3.org/TR/json-ld11/
- W3C, RDFa 1.1 Primer: https://www.w3.org/TR/rdfa-primer/
- W3C, RDFa Lite 1.1: https://www.w3.org/TR/rdfa-lite/
- W3C, HTML Microdata: https://www.w3.org/TR/microdata/
- schema.org, Getting started (all three syntaxes): https://schema.org/docs/gs.html
