<rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:webfeeds="http://webfeeds.org/rss/1.0" version="2.0"><channel><webfeeds:logo>https://vasters.com/clemens/images/zenicon.jpg</webfeeds:logo><title>Clemens Vasters</title><link>https://vasters.com/clemens/</link><description>Football. Cloud. Tech. Liberal Politics. Pictures - Principal Architect for        Messaging/Eventing at Microsoft.</description><image><url>https://vasters.com/clemens/images/zenicon.jpg</url><title>Clemens Vasters</title><link>https://vasters.com/clemens/</link></image><copyright>Clemens Vasters</copyright><lastBuildDate>Wed, 15 Jul 2026 09:51:50 GMT</lastBuildDate><managingEditor>clemens@vasters.com</managingEditor><webMaster>clemens@vasters.com</webMaster><item><trackback:ping>https://vasters.com/clemens/feed/trackback/05b389aa-29b7-48c9-9317-98fb62f483a0</trackback:ping><pingback:server>https://vasters.com/clemens/feed/pingback</pingback:server><pingback:target>https://vasters.com/clemens/post/05b389aa-29b7-48c9-9317-98fb62f483a0</pingback:target><dc:creator /><title>xRegistry hits RC3: one spec to describe — and generate — your entire messaging fabric</title><guid isPermaLink="false">https://vasters.com/clemens/post/05b389aa-29b7-48c9-9317-98fb62f483a0</guid><link>https://vasters.com/clemens/2026/07/15/xregistry-hits-rc3-one-spec-to-describe-and-generate-your-entire-messaging-fabric</link><pubDate>Wed, 15 Jul 2026 09:51:50 GMT</pubDate><description>&lt;div&gt;&lt;p class="code-line" dir="auto" data-line="6"&gt;&lt;strong&gt;The CNCF xRegistry working group has shipped Release Candidate 3 (RC3) of the xRegistry specification set &amp;mdash; the last feedback window before 1.0.&lt;/strong&gt;&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="8"&gt;If you run anything event-driven, this is worth 5 minutes. xRegistry can now describe what you send to, and expect back from, practically&amp;nbsp;&lt;strong&gt;any&lt;/strong&gt;&amp;nbsp;standard messaging channel &amp;mdash; a Kafka topic, an AMQP queue, an MQTT topic tree &amp;mdash; and generate the producer and consumer code from that description.&lt;/p&gt;
&lt;h2 id="why-it-matters" class="code-line" dir="auto" data-line="10"&gt;Why it matters&lt;/h2&gt;
&lt;p class="code-line code-active-line" dir="auto" data-line="12"&gt;CloudEvents harmonized the&amp;nbsp;&lt;em&gt;shape&lt;/em&gt;&amp;nbsp;of an event. It left four questions unanswered:&lt;/p&gt;
&lt;ul class="code-line" dir="auto" data-line="14"&gt;
&lt;li class="code-line" dir="auto" data-line="14"&gt;&lt;strong&gt;Discovery&lt;/strong&gt;&amp;nbsp;&amp;mdash; Where do I produce or consume this? What endpoints exist?&lt;/li&gt;
&lt;li class="code-line" dir="auto" data-line="15"&gt;&lt;strong&gt;Validation&lt;/strong&gt;&amp;nbsp;&amp;mdash; How do I check an event's structure and its metadata?&lt;/li&gt;
&lt;li class="code-line" dir="auto" data-line="16"&gt;&lt;strong&gt;Versioning&lt;/strong&gt;&amp;nbsp;&amp;mdash; How do events and endpoints evolve without breaking consumers?&lt;/li&gt;
&lt;li class="code-line" dir="auto" data-line="17"&gt;&lt;strong&gt;Serialization&lt;/strong&gt;&amp;nbsp;&amp;mdash; What envelope and schema format is on the wire?&lt;/li&gt;
&lt;/ul&gt;
&lt;p class="code-line" dir="auto" data-line="19"&gt;Schema registries answer some of this &amp;mdash; but every broker ships its own, each vendor- and protocol-specific. When an event crosses brokers, clients wrestle with mismatched registries.&amp;nbsp;&lt;strong&gt;xRegistry is the vendor-neutral layer that makes the metadata portable across all of them.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="what-it-is" class="code-line" dir="auto" data-line="21"&gt;What it is&lt;/h2&gt;
&lt;p class="code-line" dir="auto" data-line="23"&gt;&lt;strong&gt;A generic, extensible framework for managing metadata of any kind.&lt;/strong&gt;&amp;nbsp;At its core, an xRegistry is a simple tree:&lt;/p&gt;
&lt;blockquote class="code-line" dir="auto" data-line="25"&gt;
&lt;p class="code-line" dir="auto" data-line="25"&gt;&lt;strong&gt;Registry &amp;rarr; Group &amp;rarr; Resource &amp;rarr; Version&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p class="code-line" dir="auto" data-line="27"&gt;Groups collect related Resources (think folders). Resources are the items of interest (think files), each optionally carrying a domain-specific document &amp;mdash; like a schema &amp;mdash; and optionally versioned. That's the whole model. Everything else is extension.&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="29"&gt;&lt;strong&gt;The defining trait: one symmetric shape, three forms.&lt;/strong&gt;&amp;nbsp;The same registry can live as:&lt;/p&gt;
&lt;ul class="code-line" dir="auto" data-line="31"&gt;
&lt;li class="code-line" dir="auto" data-line="31"&gt;&lt;strong&gt;A file&lt;/strong&gt;&amp;nbsp;&amp;mdash; a single JSON manifest you check into Git next to your code.&lt;/li&gt;
&lt;li class="code-line" dir="auto" data-line="32"&gt;&lt;strong&gt;A static website&lt;/strong&gt;&amp;nbsp;&amp;mdash; one file per entity on plain storage (S3, GitHub Pages). No compute, no server logic.&lt;/li&gt;
&lt;li class="code-line" dir="auto" data-line="33"&gt;&lt;strong&gt;A full API&lt;/strong&gt;&amp;nbsp;&amp;mdash; a live service with search, filter, and write access for multiple teams.&lt;/li&gt;
&lt;/ul&gt;
&lt;p class="code-line" dir="auto" data-line="35"&gt;You can start as a hand-written file and export your way up to an API as you grow &amp;mdash;&amp;nbsp;&lt;strong&gt;no rewrite, because the representations are designed to be symmetric.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="what-it-does-for-messaging" class="code-line" dir="auto" data-line="37"&gt;What it does for messaging&lt;/h2&gt;
&lt;p class="code-line" dir="auto" data-line="39"&gt;Layered on that core is a&amp;nbsp;&lt;strong&gt;messaging and eventing catalog&lt;/strong&gt;&amp;nbsp;built from three companion specs &amp;mdash; Endpoints, Messages, and Schemas.&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="41"&gt;Together they let you declare structured data flows over the protocols people actually use &amp;mdash;&amp;nbsp;&lt;strong&gt;AMQP, MQTT, Kafka, HTTP, and NATS&lt;/strong&gt;&amp;nbsp;&amp;mdash; with or without the CloudEvents envelope, against a schema registry of&amp;nbsp;&lt;em&gt;your&lt;/em&gt;&amp;nbsp;choice (JSON Schema, Avro, Protobuf, and more).&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="43"&gt;&lt;strong&gt;The payoff:&lt;/strong&gt;&amp;nbsp;a single manifest can fully describe an interface &amp;mdash; the endpoints, the messages that flow over them, each message's Kafka key / AMQP subject / MQTT topic, a shared base CloudEvent definition, and the payload schemas each message points to.&lt;/p&gt;
&lt;h2 id="from-description-to-running-code" class="code-line" dir="auto" data-line="45"&gt;From description to running code&lt;/h2&gt;
&lt;p class="code-line" dir="auto" data-line="47"&gt;This is where it stops being documentation and starts saving work.&lt;/p&gt;
&lt;ul class="code-line" dir="auto" data-line="49"&gt;
&lt;li class="code-line" dir="auto" data-line="49"&gt;&lt;strong&gt;Generate data contracts&lt;/strong&gt;&amp;nbsp;&amp;mdash; because schemas live beside the code in source control, tooling recreates typed data classes exactly in sync with the schema version.&lt;/li&gt;
&lt;li class="code-line" dir="auto" data-line="50"&gt;&lt;strong&gt;Generate producers and consumers&lt;/strong&gt;&amp;nbsp;&amp;mdash; from a vendor-agnostic definition, tooling emits broker-specific senders and receivers.&lt;/li&gt;
&lt;li class="code-line" dir="auto" data-line="51"&gt;&lt;strong&gt;Validate on publish&lt;/strong&gt;&amp;nbsp;&amp;mdash; a server can reject events that don't match the contract, killing poison messages at the door.&lt;/li&gt;
&lt;li class="code-line" dir="auto" data-line="52"&gt;&lt;strong&gt;Shrink payloads&lt;/strong&gt;&amp;nbsp;&amp;mdash; with schemas centralized, you can drop schema info from the wire and still analyze data accurately.&lt;/li&gt;
&lt;/ul&gt;
&lt;p class="code-line" dir="auto" data-line="54"&gt;The reference&amp;nbsp;&lt;strong&gt;codegen&lt;/strong&gt;&amp;nbsp;is an extensible, Jinja2-based framework that produces senders and receivers in several languages, honoring every declared attribute.&lt;/p&gt;
&lt;h2 id="overlay-it-on-what-you-already-have" class="code-line" dir="auto" data-line="56"&gt;Overlay it on what you already have&lt;/h2&gt;
&lt;p class="code-line" dir="auto" data-line="58"&gt;xRegistry doesn't demand you move your assets into it. Via the&amp;nbsp;&lt;strong&gt;xrproxy&lt;/strong&gt;&amp;nbsp;project, an API server can&amp;nbsp;&lt;strong&gt;project other registries into the xRegistry model&lt;/strong&gt;&amp;nbsp;and proxy them &amp;mdash; leaving the source of truth in place.&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="60"&gt;In one live demo, a single xRegistry API sits in front of&amp;nbsp;&lt;strong&gt;PyPI, npm, Maven, NuGet, Microsoft's OCI container registry, and the Model Context Protocol registry&lt;/strong&gt;. Each has its own xRegistry model, so all six become one&amp;nbsp;&lt;strong&gt;navigable, type-safe metadata graph&lt;/strong&gt;&amp;nbsp;&amp;mdash; with cross-references between a container, the package inside it, the endpoint it exposes, and the event schemas that endpoint accepts.&lt;/p&gt;
&lt;h2 id="see-it-running" class="code-line" dir="auto" data-line="62"&gt;See it running&lt;/h2&gt;
&lt;p class="code-line" dir="auto" data-line="64"&gt;Four things you can open right now:&lt;/p&gt;
&lt;ul class="code-line" dir="auto" data-line="66"&gt;
&lt;li class="code-line" dir="auto" data-line="66"&gt;&lt;strong&gt;The viewer + proxy&lt;/strong&gt; &amp;mdash; &lt;a href="https://xregistry-pkg-registries-prod.redbeach-4fd4df68.westeurope.azurecontainerapps.io/viewer/" target="_blank" rel="noopener"&gt;browse those six package/container registries&lt;/a&gt; through one consistent, type-safe API.&amp;nbsp;&lt;/li&gt;
&lt;li class="code-line" dir="auto" data-line="67"&gt;&lt;strong&gt;The codegen gallery&lt;/strong&gt;&amp;nbsp;&amp;mdash; messaging senders and receivers generated from xRegistry APIs and documents, across several languages:&amp;nbsp;&lt;a href="https://xregistry.io/codegen/gallery/" data-href="https://xregistry.io/codegen/gallery/"&gt;https://xregistry.io/codegen/gallery/&lt;/a&gt;&lt;/li&gt;
&lt;li class="code-line" dir="auto" data-line="68"&gt;&lt;strong&gt;A live server&lt;/strong&gt;&amp;nbsp;&amp;mdash; a hosted&amp;nbsp;&lt;code&gt;xrserver&lt;/code&gt;&amp;nbsp;reference instance you can walk as a table or as raw JSON:&amp;nbsp;&lt;a href="https://xregistry.soaphub.org/ui/" data-href="https://xregistry.soaphub.org/ui/"&gt;https://xregistry.soaphub.org/ui/&lt;/a&gt;&amp;nbsp;(see&amp;nbsp;&lt;em&gt;CloudEvents&lt;/em&gt;&amp;nbsp;for the messaging registry,&amp;nbsp;&lt;em&gt;APIs-Guru&lt;/em&gt;&amp;nbsp;for the API-registry domain).&lt;/li&gt;
&lt;li class="code-line" dir="auto" data-line="69"&gt;&lt;strong&gt;A real manifest&lt;/strong&gt;&amp;nbsp;&amp;mdash; &lt;a href="https://github.com/clemensv/real-time-sources/blob/main/feeders/pegelonline/xreg/pegelonline.xreg.json"&gt;abstract Kafka/MQTT/AMQP endpoints bound to message groups&lt;/a&gt;, messages linking to JSON Structure schemas with equivalent Avro alongside. Zoom out to the parent folders and the MQTT, AMQP, and Kafka producer clients plus schema data classes are&amp;nbsp;&lt;strong&gt;100% generated from that manifest.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="go-deeper" class="code-line" dir="auto" data-line="71"&gt;Go deeper&lt;/h2&gt;
&lt;p class="code-line" dir="auto" data-line="73"&gt;A few design choices worth knowing before you build:&lt;/p&gt;
&lt;ul class="code-line" dir="auto" data-line="75"&gt;
&lt;li class="code-line" dir="auto" data-line="75"&gt;&lt;strong&gt;Federation by shadowing, not syncing.&lt;/strong&gt;&amp;nbsp;There's no synchronization API by design. Instead, registries layer: a local registry overrides or extends an underlying one without copying it &amp;mdash; a file can shadow a folder, a folder can shadow an API, an API can shadow another API.&amp;nbsp;&lt;em&gt;For 1.0, treat shadowing as an emerging best practice &amp;mdash; powerful, but still gaining real-world mileage.&lt;/em&gt;&lt;/li&gt;
&lt;li class="code-line" dir="auto" data-line="76"&gt;&lt;strong&gt;Catalog, not container.&lt;/strong&gt;&amp;nbsp;A registry references far more than it stores. Documents can be embedded (inline or base64) or linked by URL &amp;mdash; so you can catalog existing files where they already sit.&lt;/li&gt;
&lt;li class="code-line" dir="auto" data-line="77"&gt;&lt;strong&gt;Flat groups, dotted names.&lt;/strong&gt;&amp;nbsp;The tree is deliberately one level deep (Groups don't nest). Hierarchy comes from dot-notation IDs like&amp;nbsp;&lt;code&gt;Contoso.ERP.Orders&lt;/code&gt;&amp;nbsp;and from free-form&amp;nbsp;&lt;code&gt;labels&lt;/code&gt;&amp;nbsp;for cross-cutting queries &amp;mdash; without the complexity of nested containers.&lt;/li&gt;
&lt;li class="code-line" dir="auto" data-line="78"&gt;&lt;strong&gt;Deliberately out of scope.&lt;/strong&gt;&amp;nbsp;Authentication and authorization are left to the hosting environment. So are formal relationships&amp;nbsp;&lt;em&gt;between&lt;/em&gt;&amp;nbsp;channels &amp;mdash; the focus for 1.0 is describing a single channel precisely first.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="whats-next" class="code-line" dir="auto" data-line="80"&gt;What's next&lt;/h2&gt;
&lt;p class="code-line" dir="auto" data-line="82"&gt;RC3 is the&amp;nbsp;&lt;strong&gt;final call for feedback&lt;/strong&gt;&amp;nbsp;before xRegistry 1.0. If you work with events, schemas, or package/container/API registries, this is the moment to pressure-test the model against your use case.&lt;/p&gt;
&lt;ul class="code-line" dir="auto" data-line="84"&gt;
&lt;li class="code-line" dir="auto" data-line="84"&gt;&lt;strong&gt;Read the primer:&lt;/strong&gt;&amp;nbsp;&lt;a href="https://xregistry.io/xreg/xregistryspecs/core-v1/docs/primer.html" data-href="https://xregistry.io/xreg/xregistryspecs/core-v1/docs/primer.html"&gt;https://xregistry.io/xreg/xregistryspecs/core-v1/docs/primer.html&lt;/a&gt;&lt;/li&gt;
&lt;li class="code-line" dir="auto" data-line="85"&gt;&lt;strong&gt;Read the spec:&lt;/strong&gt;&amp;nbsp;&lt;a href="https://github.com/xregistry/spec" data-href="https://github.com/xregistry/spec"&gt;https://github.com/xregistry/spec&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-bottom-line" class="code-line" dir="auto" data-line="87"&gt;The bottom line&lt;/h2&gt;
&lt;p class="code-line" dir="auto" data-line="89"&gt;&lt;strong&gt;xRegistry turns scattered, broker-specific metadata into one portable graph you can discover, version, validate, and generate code from &amp;mdash; as a document when at rest, an API when live, and the same shape either way.&lt;/strong&gt; RC3 is your last chance to shape it before 1.0.&lt;/p&gt;&lt;/div&gt;</description></item><item xml:lang="en-us"><trackback:ping>https://vasters.com/clemens/feed/trackback/27ab5a41-f2b0-4cfb-8112-1b1dd47b61c0</trackback:ping><pingback:server>https://vasters.com/clemens/feed/pingback</pingback:server><pingback:target>https://vasters.com/clemens/post/27ab5a41-f2b0-4cfb-8112-1b1dd47b61c0</pingback:target><dc:creator /><title> Avrotize &amp; Structurize 3.0 is here!</title><guid isPermaLink="false">https://vasters.com/clemens/post/27ab5a41-f2b0-4cfb-8112-1b1dd47b61c0</guid><link>https://vasters.com/clemens/2025/12/13/avrotize-structurize-30-is-here</link><pubDate>Sat, 13 Dec 2025 12:31:27 GMT</pubDate><description>&lt;div&gt;&lt;p&gt;Just before I vanish into the holiday break, I bundled up the release of Avrotize 3.0, a major update that introduces&amp;nbsp;support for JSON Structure&amp;nbsp;&amp;ndash; a new intermediate schema format that bridges the gap between JSON Schema's familarity and expressiveness and Avro's type safety.&lt;br&gt;&lt;br&gt;What's JSON Structure?&lt;br&gt;&lt;br&gt;It's a JSON-based schema format with features Avro doesn't have:&lt;br&gt;- Discriminated unions with&amp;nbsp;$discriminator&lt;br&gt;- Schema composition via&amp;nbsp;$offers/$uses&lt;br&gt;- Validation keywords (minLength, pattern, etc.)&lt;br&gt;- Type inheritance with&amp;nbsp;$extends&lt;br&gt;&lt;br&gt;Why does this matter?&lt;br&gt;&lt;br&gt;You can now convert the structures from OpenAPI specs, JSON Schema, or CDDL directly into production-ready entity classes for C#, Java, Python, Go, TypeScript, Rust, and C++ &amp;ndash; without losing type fidelity along the way.&lt;br&gt;&lt;br&gt;Introducing Structurize&lt;br&gt;&lt;br&gt;If you're primarily working with JSON Structure and don't need Avro conversions, the&amp;nbsp;structurize&amp;nbsp;package is also available on PyPI. Currently an alias for avrotize, it will become a focused, standalone JSON Structure toolkit in a future release.&lt;br&gt;&lt;br&gt;📦&amp;nbsp;pip install structurize&lt;br&gt;&lt;br&gt;New in Avrotize 3.0:&lt;br&gt;- 35 new commands (now 62 total)&lt;br&gt;- OpenAPI 3.x &amp;rarr; JSON Structure converter&lt;br&gt;- Database schema generation for SQL, Cassandra, Kusto, DynamoDB, Elasticsearch, CosmosDB, and more&lt;br&gt;- C# generators now support MessagePack, Protobuf-net, and CBOR&lt;br&gt;- Java/TypeScript test instance factories&lt;br&gt;&lt;br&gt;See it in action&lt;br&gt;&lt;br&gt;Check out the gallery with well over 100 conversion examples at&lt;/p&gt;
&lt;div class="opengraph-preview"&gt;
&lt;div class="opengraph-preview-site"&gt;&lt;a href="https://clemensv.github.io/avrotize/"&gt;Home | Avrotize &amp;amp; Structurize&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&amp;ndash; see how schemas from various formats translate into generated code across all supported languages and many database schema dialects.&lt;br&gt;&lt;br&gt;Key roadmap item for v4: Instance data transcoders; e.g. pipe XML data conforming to to a source XSD into the transcoder and get JSON output that conforms to the JSON Structure schema produced by the schema conversion. (That does largely already work with the code generators that support multiple encodings at the same time, with C# having most options)&lt;br&gt;&lt;br&gt;📦&amp;nbsp;pip install avrotize&lt;br&gt;🔗&lt;a href="https://github.com/clemensv/avrotize"&gt;clemensv/avrotize: Avrotize is a command-line tool for converting data structure definitions between different schema formats, using Apache Avro Schema as the integration schema model.&lt;/a&gt;&lt;br&gt;&lt;br&gt;Happy holidays! 🎅&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/div&gt;</description></item><item><trackback:ping>https://vasters.com/clemens/feed/trackback/b1a63ea3-0de3-4b16-b70a-152781eca422</trackback:ping><pingback:server>https://vasters.com/clemens/feed/pingback</pingback:server><pingback:target>https://vasters.com/clemens/post/b1a63ea3-0de3-4b16-b70a-152781eca422</pingback:target><dc:creator /><title>JSON Structure - An Introduction</title><guid isPermaLink="false">https://vasters.com/clemens/post/b1a63ea3-0de3-4b16-b70a-152781eca422</guid><link>https://vasters.com/clemens/2025/12/05/json-structure-an-introduction</link><pubDate>Fri, 05 Dec 2025 09:13:19 GMT</pubDate><description>&lt;div&gt;&lt;header id="title-block-header"&gt;&lt;/header&gt;
&lt;p&gt;This &lt;a href="https://json-structure.org/json-structure-primer.html"&gt;primer&lt;/a&gt; introduces&amp;nbsp;&lt;a href="https://json-structure.org"&gt;&lt;em&gt;JSON Structure&lt;/em&gt;&lt;/a&gt;, a modern, strictly typed data definition language that resembles JSON Schema, but has very different basic design principles.&lt;/p&gt;
&lt;p&gt;JSON Structure focuses on defining data types with clear, deterministic constraints while supporting extensions for precise representations of numbers, dates, and more.&lt;/p&gt;
&lt;p&gt;Common programming language concepts like reuse and composition are supported directly in the schema language, but while avoiding introduction of the entire complexity of object-oriented programming.&lt;/p&gt;
&lt;p&gt;Conditional validation of JSON data against schemas with composition constructs like &lt;code&gt;anyOf&lt;/code&gt; or &lt;code&gt;allOf&lt;/code&gt; is availble in JSON Structure quite similar to JSON Schema, has been split out into optional extensions, allowing simple data definitions to remain lightweight and easy to understand.&lt;/p&gt;
&lt;h2 id="introduction"&gt;1. Introduction&lt;/h2&gt;
&lt;p&gt;There are rapidly growing needs for a standardized (IETF RFC) schema language that can describe data types and structures and whose definitions map cleanly to programming language types and database constructs as well as into the popular JSON data encoding. The type model needs to reflect the needs of modern applications and it must allow rich annotations with semantic information that can be evaluated and understood by developers and by large language models (LLMs).&lt;/p&gt;
&lt;p&gt;JSON Schema has been in development since ca. 2009 and has gone through several iterations. The industry has largely settled on &amp;ldquo;Draft 7&amp;rdquo; of JSON Schema, with subsequent releases seeing comparatively weak adoption. There&amp;rsquo;s substantial frustration that many developers have with JSON Schema because they try to use it for scenarios that it was not designed for. JSON Schema is a powerful document validation tool, but it is not a data definition language. Frustration with JSON Schema is widespread across the industry&amp;mdash;and yet it remains popular due to lack of good alternatives.&lt;/p&gt;
&lt;p&gt;Apache Avro is an alternative that has gained traction in the data community because it&amp;rsquo;s much easier to create tooling on top of. However, Avro&amp;rsquo;s type system is limited and its syntax is unfamiliar to most developers.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;JSON Structure&lt;/em&gt; aims to combine the tooling-friendliness of Avro with the familiar type definition shapes of JSON Schema while providing an overall broader type system and data documentation/qualification capabilities that provide richer context for AI/LLMs trying to understand data structures.&lt;/p&gt;
&lt;p&gt;While JSON Schema focuses on and excels at document validation, JSON Structure focuses on being a strong data definition language.&lt;/p&gt;
&lt;p&gt;There are two major use-case scenarios for schema languages in general:&lt;/p&gt;
&lt;ol type="1"&gt;
&lt;li&gt;Validating JSON data against a schema to ensure conformity to a specific structure and constraints.&lt;/li&gt;
&lt;li&gt;Declaring data types and structures in a machine-readable format that can be used to generate code, documentation, or other artifacts across platforms and languages.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;JSON Schema provides powerful facilities for the first use-case. JSON Structure prioritizes the second use-case while still supporting the validation scenarios similar to JSON Schema through extensions.&lt;/p&gt;
&lt;p&gt;With JSON Structure, we&amp;rsquo;ve designed a type system that addresses common challenges:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Clear mapping to programming language types&lt;/li&gt;
&lt;li&gt;Support for more precise numeric types and date/time representations&lt;/li&gt;
&lt;li&gt;Modular approach to extensions&lt;/li&gt;
&lt;li&gt;Simplified cross-references between schema documents&lt;/li&gt;
&lt;li&gt;Straightforward reuse patterns for types&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This approach better supports code generation, database mappings, and integration with modern programming languages, while keeping the validation capabilities as optional extensions for those who need them.&lt;/p&gt;
&lt;h2 id="design-principles"&gt;2. Design Principles&lt;/h2&gt;
&lt;p&gt;JSON Structure is designed with the following principles in mind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Scope&lt;/strong&gt;: JSON Structure &amp;ldquo;Core&amp;rdquo; is meant to be a sufficient language for a &amp;ldquo;schema first&amp;rdquo; approach to defining application data structures in &amp;ldquo;polyglot&amp;rdquo; environments where such definitions are shared across application modules and tiers and databases and caches and other data stores. It is not a goal to be able to capture, say, all intricacies of a C++ class and express those. In that way, JSON Structure definitions are meant to be authoritative. Tools should be able to map from JSON Structure to programming language constructs and, within reasonable bounds, to database structures without losing structural information, but the reverse might not always be true.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Relation to JSON&lt;/strong&gt;: JSON Structure is expressed in JSON and has built-in rules for how types are mapped to JSON encoding, but the data definitions can be seen as being independent of JSON. You can declare an &lt;em&gt;object&lt;/em&gt; type in JSON Structure and use that type to code-generate a record class for an Object-Relational-Mapping framework and a corresponding database table without JSON encoding ever playing a role.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Familiarity&lt;/strong&gt;: Millions of software developers recognize declarations of the shape &lt;em&gt;&amp;ldquo;type&amp;rdquo;:&amp;ldquo;object&amp;rdquo;, &amp;ldquo;properties&amp;rdquo;: {&amp;hellip;}&lt;/em&gt; as what a &amp;ldquo;schema&amp;rdquo; should look like and it&amp;rsquo;s often the only formal schema model they a have encountered. In spite of its shortcomings as a data definition language, JSON Schema&amp;rsquo;s most basic expressions for to declare a type are etched into people&amp;rsquo;s minds and any improvement that does not pick people up from where they are&amp;acute;will have it harder to gain substantial traction.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Simplicity&lt;/strong&gt;: JSON Structure is designed to be simple and easy to understand. The schema language is designed to be easy to read and write, with a focus on clear and concise definitions. The type system is meant to easily align with concepts people use and need in their programming and database work, including safe numeric expressions and date and time expressions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pragmatism&lt;/strong&gt;: JSON Structure is designed to be a pragmatic data definition language for application developers and not a language for metadata geeks. That means that when there is tension between providing type definitions for application use-cases and being able to describe or validate any imaginable JSON expression, the application use-cases win.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optional Complexity&lt;/strong&gt;: JSON Structure &amp;ldquo;Core&amp;rdquo; documents are always self-contained and simple to understand and process. If the user needs further capabilities like imports of definitions from external files, semantic annotations, or complex validation hints, they can opt into those by using companion specifications, potentially at the expense of compatibility with implementations of JSON Structure that are restricted to the &amp;ldquo;Core&amp;rdquo; specification.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="key-concepts"&gt;3. Key Concepts&lt;/h2&gt;
&lt;p&gt;JSON Structure is designed to look and feel very much like the JSON Schema&lt;/p&gt;
&lt;p&gt;drafts you already know, but some rules have been tightened up to make it easier to understand and use. Therefore, existing JSON Schema documents may need to be updated to conform to the new rules.&lt;/p&gt;
&lt;h3 id="differences-to-json-schema-drafts"&gt;3.1. Differences to JSON Schema Drafts&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Strict Typing:&lt;/strong&gt; Every schema must explicitly specify its data type. For compound types (objects, arrays, sets), additional required metadata like a name and other required property definitions help enforce structured data.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Identifiers:&lt;/strong&gt; Names of types and properties are restricted to the regular expression &lt;code&gt;[A-Za-z_][A-Za-z0-9_]*&lt;/code&gt; to make them easier to map to code and database constructs. Map keys may additionally contain &lt;code&gt;:&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;, and &lt;code&gt;.&lt;/code&gt; and may start with a digit.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Extended Types:&lt;/strong&gt; In addition to JSON primitives such as string, number, boolean, and null, JSON Structure Core supports many extended primitive types (e.g., &lt;code&gt;int32&lt;/code&gt;, &lt;code&gt;int64&lt;/code&gt;, &lt;code&gt;decimal&lt;/code&gt;, &lt;code&gt;date&lt;/code&gt;, &lt;code&gt;uuid&lt;/code&gt;) for high precision or format-specific data.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Compound Types:&lt;/strong&gt; The compound types have been extended to include &lt;code&gt;set&lt;/code&gt;, &lt;code&gt;map&lt;/code&gt;, and &lt;code&gt;tuple&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Object:&lt;/strong&gt; Define structured data with a required &lt;code&gt;name&lt;/code&gt; and a set of &lt;code&gt;properties&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Array:&lt;/strong&gt; List of items where the &lt;code&gt;items&lt;/code&gt; attribute references a declared type without inline compound definitions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Set:&lt;/strong&gt; An unordered collection of unique elements.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Map:&lt;/strong&gt; A collection of key-value pairs where keys are strings and values are of a declared type.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tuple:&lt;/strong&gt; A fixed-length array of elements where each element is of a declared type. It&amp;rsquo;s a more compact alternative to objects where the property names are replaced by the position in the tuple. Arrays or maps of tuples are especially useful for time-series data.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Choice:&lt;/strong&gt; A discriminated union of types, where one of the types is selected based on a discriminator property. The &lt;code&gt;choice&lt;/code&gt; keyword is used to define the union and the &lt;code&gt;selector&lt;/code&gt; property is used to specify the discriminator property.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Namespaces:&lt;/strong&gt; Namespaces are a formal part of the schema language, allowing for more modular and deterministic schema definitions. Namespaces are used to scope type definitions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cross-Referencing:&lt;/strong&gt; The &lt;code&gt;$ref&lt;/code&gt; keyword has been limited to referencing named types that exist within the same document. It can no longer reference and insert arbitrary JSON nodes and it can no longer reference external documents. To reuse types from other documents, you now need to use the &lt;code&gt;$import&lt;/code&gt; keyword from the optional &lt;a href="https://github.com/json-structure/import"&gt;import&lt;/a&gt; spec to import the types you need. Once imported, you can reference types with &lt;code&gt;$ref&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="extensibility-model"&gt;3.2. Extensibility Model&lt;/h3&gt;
&lt;p&gt;JSON Structure is designed to be extensible. Any schema can be extended with custom keywords given that those do not conflict with the core schema language or companion specifications that are &amp;ldquo;activated&amp;rdquo; for the schema document. It&amp;rsquo;s recommended for custom keywords to have a compnay- or project-specific prefix to avoid such collisions. It&amp;rsquo;s not required to declare a formal meta-schema to use custom keywords, but it&amp;rsquo;s recommended to do so.&lt;/p&gt;
&lt;p&gt;JSON Structure is designed to be modular. The core schema language is defined in the &lt;a href="https://github.com/json-structure/core"&gt;JSON Structure Core&lt;/a&gt; document. Companion specifications provide additional features and capabilities that can be used to extend the core schema language.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;abstract&lt;/code&gt; and &lt;code&gt;$extends&lt;/code&gt; keywords enable controlled type extension, supporting basic object-oriented-programming-style inheritance while not permitting subtype polymorphism where a sub-type value can be assigned a base-typed property. This approach avoids validation complexities and mapping issues between JSON schemas, programming types, and databases.&lt;/p&gt;
&lt;p&gt;There are two types of formal extensions: &lt;em&gt;extensible types&lt;/em&gt; and &lt;em&gt;add-in types&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id="extensible-types"&gt;3.3. Extensible Types&lt;/h3&gt;
&lt;p&gt;It&amp;rsquo;s fairly common that different types share a common basic set of properties. In JSON Schema itself, the &lt;code&gt;description&lt;/code&gt; property is a good example of a property that is shared across all schema and non-schema objects.&lt;/p&gt;
&lt;p&gt;An &lt;em&gt;extensible type&lt;/em&gt; is declared as &lt;code&gt;abstract&lt;/code&gt; and provides a set of common definitions to be shared by extensions. For example, a base type &lt;em&gt;AddressBase&lt;/em&gt; MAY be extended by &lt;em&gt;StreetAddress&lt;/em&gt; and &lt;em&gt;PostOfficeBoxAddress&lt;/em&gt; via &lt;code&gt;$extends&lt;/code&gt;. Because it&amp;rsquo;s abstract, &lt;em&gt;AddressBase&lt;/em&gt; cannot be used directly anywhere as a type, however. &lt;em&gt;Address&lt;/em&gt; extends &lt;em&gt;AddressBase&lt;/em&gt; without adding any additional properties.&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;div id="cb1" class="sourceCode"&gt;
&lt;pre class="sourceCode json"&gt;&lt;code class="sourceCode json"&gt;&lt;span id="cb1-1"&gt;&lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-2"&gt;    &lt;span class="dt"&gt;"$schema"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"https://json-structure.org/meta/core/v0/#"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-3"&gt;    &lt;span class="dt"&gt;"definitions"&lt;/span&gt; &lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-4"&gt;      &lt;span class="dt"&gt;"AddressBase"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-5"&gt;        &lt;span class="dt"&gt;"abstract"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-6"&gt;        &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"object"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-7"&gt;        &lt;span class="dt"&gt;"properties"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-8"&gt;            &lt;span class="dt"&gt;"city"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-9"&gt;            &lt;span class="dt"&gt;"state"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-10"&gt;            &lt;span class="dt"&gt;"zip"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-11"&gt;        &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-12"&gt;      &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-13"&gt;      &lt;span class="dt"&gt;"StreetAddress"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-14"&gt;        &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"object"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-15"&gt;        &lt;span class="dt"&gt;"$extends"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"#/definitions/AddressBase"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-16"&gt;        &lt;span class="dt"&gt;"properties"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-17"&gt;            &lt;span class="dt"&gt;"street"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-18"&gt;        &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-19"&gt;      &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-20"&gt;      &lt;span class="dt"&gt;"PostOfficeBoxAddress"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-21"&gt;        &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"object"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-22"&gt;        &lt;span class="dt"&gt;"$extends"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"#/definitions/AddressBase"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-23"&gt;        &lt;span class="dt"&gt;"properties"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-24"&gt;            &lt;span class="dt"&gt;"poBox"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-25"&gt;        &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-26"&gt;      &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-27"&gt;      &lt;span class="dt"&gt;"Address"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-28"&gt;        &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"object"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-29"&gt;        &lt;span class="dt"&gt;"$extends"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"#/definitions/AddressBase"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-30"&gt;      &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-31"&gt;    &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-32"&gt;&lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id="add-in-types"&gt;3.4. Add-in Types&lt;/h3&gt;
&lt;p&gt;Add-in types allow modifying any existing type in a schema with additional properties or constraints. Add-ins are offered to the instance document author through the &lt;code&gt;$offers&lt;/code&gt; keywords in the schema document. The instance document author can then enable the add-in by referencing the add-in name in the &lt;code&gt;$uses&lt;/code&gt; keyword. When the instance document does so, the add-in properties are injected into the designated schema types before the schema is evaluated. Enabled add-ins are treated as if they were part of the schema from the beginning.&lt;/p&gt;
&lt;p&gt;Add-ins can also be enabled in meta-schemas such that they are always applied to schemas that are based on the meta-schema.&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;add-in type&lt;/em&gt; is declared as &lt;code&gt;abstract&lt;/code&gt; and &lt;code&gt;$extends&lt;/code&gt; a specific type that does not need to be abstract. For example, a add-in type &lt;em&gt;DeliveryInstructions&lt;/em&gt; might be applied to any &lt;em&gt;StreetAddress&lt;/em&gt; types in a document:&lt;/p&gt;
&lt;div id="cb2" class="sourceCode"&gt;
&lt;pre class="sourceCode json"&gt;&lt;code class="sourceCode json"&gt;&lt;span id="cb2-1"&gt;&lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-2"&gt;    &lt;span class="dt"&gt;"$schema"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"https://json-structure.org/meta/core/v0/#"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-3"&gt;    &lt;span class="dt"&gt;"$id"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"https://schemas.vasters.com/Addresses"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-4"&gt;    &lt;span class="dt"&gt;"$root"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"#/definitions/StreetAddress"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-5"&gt;    &lt;span class="dt"&gt;"$offers"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-6"&gt;        &lt;span class="dt"&gt;"DeliveryInstructions"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"#/definitions/DeliveryInstructions"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-7"&gt;    &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-8"&gt;    &lt;span class="dt"&gt;"definitions"&lt;/span&gt; &lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-9"&gt;      &lt;span class="dt"&gt;"StreetAddress"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-10"&gt;        &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"object"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-11"&gt;        &lt;span class="dt"&gt;"properties"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-12"&gt;            &lt;span class="dt"&gt;"street"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-13"&gt;            &lt;span class="dt"&gt;"city"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-14"&gt;            &lt;span class="dt"&gt;"state"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-15"&gt;            &lt;span class="dt"&gt;"zip"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-16"&gt;        &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-17"&gt;      &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-18"&gt;      &lt;span class="dt"&gt;"DeliveryInstructions"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-19"&gt;        &lt;span class="dt"&gt;"abstract"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-20"&gt;        &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"object"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-21"&gt;        &lt;span class="dt"&gt;"$extends"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"#/definitions/StreetAddress"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-22"&gt;        &lt;span class="dt"&gt;"properties"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-23"&gt;            &lt;span class="dt"&gt;"instructions"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-24"&gt;        &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-25"&gt;      &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-26"&gt;    &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-27"&gt;&lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Add-ins are applied to a schema by referencing the add-in name in the &lt;code&gt;$uses&lt;/code&gt; keyword that is available only in instance documents. The &lt;code&gt;$uses&lt;/code&gt; keyword is a set of add-in names that are applied to the schema for the document.&lt;/p&gt;
&lt;div id="cb3" class="sourceCode"&gt;
&lt;pre class="sourceCode json"&gt;&lt;code class="sourceCode json"&gt;&lt;span id="cb3-1"&gt;&lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-2"&gt;  &lt;span class="dt"&gt;"$schema"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"https://schemas.vasters.com/Addresses"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-3"&gt;  &lt;span class="dt"&gt;"$uses"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="ot"&gt;[&lt;/span&gt;&lt;span class="st"&gt;"DeliveryInstructions"&lt;/span&gt;&lt;span class="ot"&gt;]&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-4"&gt;  &lt;span class="dt"&gt;"street"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"123 Main St"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-5"&gt;  &lt;span class="dt"&gt;"city"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"Anytown"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-6"&gt;  &lt;span class="dt"&gt;"state"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"QA"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-7"&gt;  &lt;span class="dt"&gt;"zip"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"00001"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-8"&gt;  &lt;span class="dt"&gt;"instructions"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"Leave at the back door"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-9"&gt;&lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id="reusing-types-across-different-schema-documents"&gt;3.5. Reusing Types across different Schema Documents&lt;/h3&gt;
&lt;p&gt;The prior versions of JSON Schema in effect allowed for &lt;code&gt;$ref&lt;/code&gt; to reference arbitrary JSON nodes from the same or external document, which made references very difficult to understand and process, especially when the references were deep links into external schema documents and/or schema documents were cross-referenced using relative URIs to avoid committing to an absolute schema location.&lt;/p&gt;
&lt;p&gt;JSON Structure has a more controlled approach to limit that complexity.&lt;/p&gt;
&lt;ol type="1"&gt;
&lt;li&gt;The &lt;code&gt;$ref&lt;/code&gt; keyword can only reference named types that exist within the same document. It can no longer reference and insert arbitrary JSON nodes and it can no longer reference external documents.&lt;/li&gt;
&lt;li&gt;To reuse types from other documents, you now need to use the &lt;code&gt;$import&lt;/code&gt; keyword from the optional &lt;a href="https://github.com/json-structure/import"&gt;import&lt;/a&gt; spec to import the types you need into the scope of the schema document. Once imported, you use the imported types as if they were declared in the document. To avoid conflicts, you can import external types into a namespace.&lt;/li&gt;
&lt;li&gt;Since types are imported and then referenced as if they were declared in the document, it&amp;rsquo;s also possible and permitted to &amp;ldquo;shadow&amp;rdquo; imported types with local definitions by explicitly declaring a type with the same name and namespace as as the imported type.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="core-and-companion-specifications"&gt;3.6. Core and Companion Specifications&lt;/h3&gt;
&lt;p&gt;The following documents are part of this JSON Structure proposal:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/json-structure/core"&gt;JSON Structure Core&lt;/a&gt;: Defines the core schema language for declaring data types and structures.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/json-structure/alternate-names"&gt;JSON Structure Alternate Names and Descriptions&lt;/a&gt;: Provides a mechanism for declaring alternate names and symbols for types and properties, including for the purposes of internationalization.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/json-structure/units"&gt;JSON Structure Symbols, Scientific Units, and Currencies&lt;/a&gt;: Defines keywords for specifying symbols, scientific units, and currency codes on types and properties.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/json-structure/conditional-composition"&gt;JSON Structure Conditional Composition&lt;/a&gt;: Defines a set of conditional composition rules for evaluating schemas.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/json-structure/validation"&gt;JSON Structure Validation&lt;/a&gt;: Specifies extensions to the core schema language for declaring validation rules.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/json-structure/import"&gt;JSON Structure Import&lt;/a&gt;: Defines a mechanism for importing external schemas and definitions into a schema document.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="meta-schemas"&gt;3.7. Meta-Schemas&lt;/h3&gt;
&lt;p&gt;Meta-schemas are JSON Structure documents that define the structure and constraints of schema documents themselves. Meta-schemas do not have special constructs beyond what is available in the core schema language.&lt;/p&gt;
&lt;p&gt;A meta-schema is referenced in a schema document using the &lt;code&gt;$schema&lt;/code&gt; keyword. The meta-schema defines the constraints that the schema document must adhere to.&lt;/p&gt;
&lt;p&gt;The value of the &lt;code&gt;$schema&lt;/code&gt; keyword is a URI that corresponds to the &lt;code&gt;$id&lt;/code&gt; declared in the meta-schema document. The URI should be a resolvable URL that points to the meta-schema document, but for well-known meta-schemas, a schema processor will typically not actually fetch the meta-schema document. Instead, the schema processor will use the URI to identify the meta-schema and validate the schema document against its copy of the meta-schema.&lt;/p&gt;
&lt;p&gt;A meta-schema can build on another meta-schema by &lt;code&gt;$import&lt;/code&gt;ing all of its definitions and then adding additional definitions or constraints or by shadowing definitions from the imported meta-schema.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://vasters.com/clemens/json-schema-core-metaschema-core.json"&gt;&amp;ldquo;core&amp;rdquo; meta-schema&lt;/a&gt; formally defines the elements described in the &lt;a href="https://github.com/json-structure/core"&gt;JSON Structure Core&lt;/a&gt; document. The &amp;ldquo;$id&amp;rdquo; of the core meta-schema is &lt;code&gt;https://json-structure.org/meta/core/v0&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://vasters.com/clemens/json-schema-metaschema-extended.json"&gt;&amp;ldquo;extended&amp;rdquo; meta-schema&lt;/a&gt; extends the core meta-schema with all additional features and capabilities provided by the companion specifications and offers those features to schema authors. The &amp;ldquo;$id&amp;rdquo; of the extended meta-schema is &lt;code&gt;https://json-structure.org/meta/extended/v0&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://vasters.com/clemens/json-schema-metaschema-validation.json"&gt;&amp;ldquo;validation&amp;rdquo; meta-schema&lt;/a&gt; enables all add-ins defined in the extended meta-schema.&lt;/p&gt;
&lt;h2 id="using-structure-core"&gt;4. Using Structure Core&lt;/h2&gt;
&lt;p&gt;This section introduces JSON Structure by example.&lt;/p&gt;
&lt;h3 id="example-declaring-a-simple-object-type"&gt;4.1. Example: Declaring a simple object type&lt;/h3&gt;
&lt;p&gt;Here is an example of a simple object type definition:&lt;/p&gt;
&lt;div id="cb4" class="sourceCode"&gt;
&lt;pre class="sourceCode json"&gt;&lt;code class="sourceCode json"&gt;&lt;span id="cb4-1"&gt;&lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-2"&gt;    &lt;span class="dt"&gt;"$schema"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"https://json-structure.org/meta/core/v0/#"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-3"&gt;    &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"object"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-4"&gt;    &lt;span class="dt"&gt;"name"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"Person"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-5"&gt;    &lt;span class="dt"&gt;"properties"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-6"&gt;        &lt;span class="dt"&gt;"firstName"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-7"&gt;        &lt;span class="dt"&gt;"lastName"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-8"&gt;        &lt;span class="dt"&gt;"dateOfBirth"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"date"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-9"&gt;    &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-10"&gt;    &lt;span class="dt"&gt;"required"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="ot"&gt;[&lt;/span&gt;&lt;span class="st"&gt;"firstName"&lt;/span&gt;&lt;span class="ot"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"lastName"&lt;/span&gt;&lt;span class="ot"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-11"&gt;&lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If you are familiar with JSON Schema, you will instantly recognize the structure of this schema. The &lt;code&gt;type&lt;/code&gt; attribute specifies that this is an object type. The &lt;code&gt;properties&lt;/code&gt; attribute lists the properties of the object, and the &lt;code&gt;required&lt;/code&gt; attribute lists the properties that are required.&lt;/p&gt;
&lt;p&gt;There are a few differences from prior version of JSON Schema. The &lt;code&gt;name&lt;/code&gt; attribute is new and is required for the root type. The &lt;code&gt;type&lt;/code&gt; attribute is also required and no longer implied to be &lt;code&gt;object&lt;/code&gt; if not present. You may also notice that the &amp;ldquo;dateOfBirth&amp;rdquo; property uses the new &lt;code&gt;date&lt;/code&gt; type, which is an extended native type.&lt;/p&gt;
&lt;h3 id="example-declaring-primitive-and-extended-types"&gt;4.2. Example: Declaring Primitive and Extended Types&lt;/h3&gt;
&lt;p&gt;Below is an example schema that defines a simple profile with a few more extended types:&lt;/p&gt;
&lt;div id="cb5" class="sourceCode"&gt;
&lt;pre class="sourceCode json"&gt;&lt;code class="sourceCode json"&gt;&lt;span id="cb5-1"&gt;&lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-2"&gt;    &lt;span class="dt"&gt;"$schema"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"https://json-structure.org/meta/core/v0/#"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-3"&gt;    &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"object"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-4"&gt;    &lt;span class="dt"&gt;"name"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"UserProfile"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-5"&gt;    &lt;span class="dt"&gt;"properties"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-6"&gt;        &lt;span class="dt"&gt;"username"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-7"&gt;        &lt;span class="dt"&gt;"dateOfBirth"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"date"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-8"&gt;        &lt;span class="dt"&gt;"lastSeen"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"datetime"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-9"&gt;        &lt;span class="dt"&gt;"score"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"int64"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-10"&gt;        &lt;span class="dt"&gt;"balance"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"decimal"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;"precision"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="dv"&gt;20&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;"scale"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-11"&gt;        &lt;span class="dt"&gt;"isActive"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"boolean"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-12"&gt;    &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-13"&gt;    &lt;span class="dt"&gt;"required"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="ot"&gt;[&lt;/span&gt;&lt;span class="st"&gt;"username"&lt;/span&gt;&lt;span class="ot"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"birthdate"&lt;/span&gt;&lt;span class="ot"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-14"&gt;&lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;int64&lt;/code&gt; type is an extended type that represents a 64-bit signed integer. The &lt;code&gt;decimal&lt;/code&gt; type is another extended type that represents a decimal number with a specified precision and scale. The &lt;code&gt;datetime&lt;/code&gt; type is an extended type that represents a date and time value.&lt;/p&gt;
&lt;h2 id="example-declaring-inline-compound-types"&gt;5. Example: Declaring inline compound types&lt;/h2&gt;
&lt;p&gt;This is an example of a type that is declared inline. This is useful for compound types that are not reused elsewhere in the schema. The &lt;code&gt;address&lt;/code&gt; property of the &lt;code&gt;UserProfile&lt;/code&gt; type references the inline &lt;code&gt;Address&lt;/code&gt; type. This type cannot be referenced from other types in the schema.&lt;/p&gt;
&lt;div id="cb6" class="sourceCode"&gt;
&lt;pre class="sourceCode json"&gt;&lt;code class="sourceCode json"&gt;&lt;span id="cb6-1"&gt;&lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-2"&gt;    &lt;span class="dt"&gt;"$schema"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"https://json-structure.org/meta/core/v0/#"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-3"&gt;    &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"object"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-4"&gt;    &lt;span class="dt"&gt;"name"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"UserProfile"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-5"&gt;    &lt;span class="dt"&gt;"properties"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-6"&gt;        &lt;span class="dt"&gt;"username"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-7"&gt;        &lt;span class="dt"&gt;"dateOfBirth"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"date"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-8"&gt;        &lt;span class="dt"&gt;"lastSeen"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"datetime"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-9"&gt;        &lt;span class="dt"&gt;"score"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"int64"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-10"&gt;        &lt;span class="dt"&gt;"balance"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"decimal"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;"precision"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="dv"&gt;20&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;"scale"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-11"&gt;        &lt;span class="dt"&gt;"isActive"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"boolean"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-12"&gt;        &lt;span class="dt"&gt;"address"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-13"&gt;            &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"object"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-14"&gt;            &lt;span class="dt"&gt;"name"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"Address"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-15"&gt;            &lt;span class="dt"&gt;"properties"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-16"&gt;                &lt;span class="dt"&gt;"street"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-17"&gt;                &lt;span class="dt"&gt;"city"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-18"&gt;                &lt;span class="dt"&gt;"state"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-19"&gt;                &lt;span class="dt"&gt;"zip"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-20"&gt;            &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-21"&gt;            &lt;span class="dt"&gt;"required"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="ot"&gt;[&lt;/span&gt;&lt;span class="st"&gt;"street"&lt;/span&gt;&lt;span class="ot"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"city"&lt;/span&gt;&lt;span class="ot"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"state"&lt;/span&gt;&lt;span class="ot"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"zip"&lt;/span&gt;&lt;span class="ot"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-22"&gt;        &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-23"&gt;    &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-24"&gt;    &lt;span class="dt"&gt;"required"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="ot"&gt;[&lt;/span&gt;&lt;span class="st"&gt;"username"&lt;/span&gt;&lt;span class="ot"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"birthdate"&lt;/span&gt;&lt;span class="ot"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-25"&gt;&lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id="example-declaring-reusable-types-in-definitions"&gt;5.1. Example: Declaring reusable types in &lt;code&gt;definitions&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;To define reusable types, you can use the &lt;code&gt;definitions&lt;/code&gt; keyword to define types that can be referenced by other types in the same document. Here is an example:&lt;/p&gt;
&lt;div id="cb7" class="sourceCode"&gt;
&lt;pre class="sourceCode json"&gt;&lt;code class="sourceCode json"&gt;&lt;span id="cb7-1"&gt;&lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-2"&gt;    &lt;span class="dt"&gt;"$schema"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"https://json-structure.org/meta/core/v0/#"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-3"&gt;    &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"object"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-4"&gt;    &lt;span class="dt"&gt;"name"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"UserProfile"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-5"&gt;    &lt;span class="dt"&gt;"properties"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-6"&gt;        &lt;span class="dt"&gt;"username"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-7"&gt;        &lt;span class="dt"&gt;"dateOfBirth"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"date"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-8"&gt;        &lt;span class="dt"&gt;"lastSeen"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"datetime"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-9"&gt;        &lt;span class="dt"&gt;"score"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"int64"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-10"&gt;        &lt;span class="dt"&gt;"balance"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"decimal"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;"precision"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="dv"&gt;20&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;"scale"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-11"&gt;        &lt;span class="dt"&gt;"isActive"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"boolean"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-12"&gt;        &lt;span class="dt"&gt;"address"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt; &lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"$ref"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"#/definitions/Address"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-13"&gt;    &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-14"&gt;    &lt;span class="dt"&gt;"required"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="ot"&gt;[&lt;/span&gt;&lt;span class="st"&gt;"username"&lt;/span&gt;&lt;span class="ot"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"birthdate"&lt;/span&gt;&lt;span class="ot"&gt;]&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-15"&gt;    &lt;span class="dt"&gt;"definitions"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-16"&gt;        &lt;span class="dt"&gt;"Address"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-17"&gt;            &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"object"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-18"&gt;            &lt;span class="dt"&gt;"properties"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-19"&gt;                &lt;span class="dt"&gt;"street"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-20"&gt;                &lt;span class="dt"&gt;"city"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-21"&gt;                &lt;span class="dt"&gt;"state"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-22"&gt;                &lt;span class="dt"&gt;"zip"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-23"&gt;            &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-24"&gt;            &lt;span class="dt"&gt;"required"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="ot"&gt;[&lt;/span&gt;&lt;span class="st"&gt;"street"&lt;/span&gt;&lt;span class="ot"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"city"&lt;/span&gt;&lt;span class="ot"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"state"&lt;/span&gt;&lt;span class="ot"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"zip"&lt;/span&gt;&lt;span class="ot"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-25"&gt;        &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-26"&gt;    &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-27"&gt;&lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In this example, the &lt;code&gt;Address&lt;/code&gt; type is declared in the &lt;code&gt;definitions&lt;/code&gt; section and can be referenced by other types in the same document using the &lt;code&gt;$ref&lt;/code&gt; keyword. Mind that the &lt;code&gt;$ref&lt;/code&gt; keyword can now only reference types declared in the &lt;code&gt;definitions&lt;/code&gt; section of the same document. The keyword can only be used where a type is expected.&lt;/p&gt;
&lt;h3 id="example-structuring-types-with-namespaces"&gt;5.2. Example: Structuring types with namespaces&lt;/h3&gt;
&lt;p&gt;Namespaces are used to scope type definitions. Here is an example of how to use namespaces to structure your types, with two differing &lt;code&gt;Address&lt;/code&gt; types:&lt;/p&gt;
&lt;div id="cb8" class="sourceCode"&gt;
&lt;pre class="sourceCode json"&gt;&lt;code class="sourceCode json"&gt;&lt;span id="cb8-1"&gt;&lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-2"&gt;    &lt;span class="dt"&gt;"$schema"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"https://json-structure.org/meta/core/v0/#"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-3"&gt;    &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"object"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-4"&gt;    &lt;span class="dt"&gt;"name"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"UserProfile"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-5"&gt;    &lt;span class="dt"&gt;"properties"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-6"&gt;        &lt;span class="dt"&gt;"username"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-7"&gt;        &lt;span class="dt"&gt;"dateOfBirth"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"date"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-8"&gt;        &lt;span class="dt"&gt;"networkAddress"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt; &lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"$ref"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"#/definitions/Network/Address"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-9"&gt;        &lt;span class="dt"&gt;"physicalAddress"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"$ref"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"#/definitions/Physical/Address"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-10"&gt;    &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-11"&gt;    &lt;span class="dt"&gt;"required"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="ot"&gt;[&lt;/span&gt;&lt;span class="st"&gt;"username"&lt;/span&gt;&lt;span class="ot"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"birthdate"&lt;/span&gt;&lt;span class="ot"&gt;]&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-12"&gt;    &lt;span class="dt"&gt;"definitions"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-13"&gt;        &lt;span class="dt"&gt;"Network"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-14"&gt;            &lt;span class="dt"&gt;"Address"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-15"&gt;                &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"object"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-16"&gt;                &lt;span class="dt"&gt;"properties"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-17"&gt;                    &lt;span class="dt"&gt;"ipv4"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-18"&gt;                    &lt;span class="dt"&gt;"ipv6"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-19"&gt;                &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-20"&gt;            &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-21"&gt;        &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-22"&gt;        &lt;span class="dt"&gt;"Physical"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-23"&gt;            &lt;span class="dt"&gt;"Address"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-24"&gt;                &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"object"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-25"&gt;                &lt;span class="dt"&gt;"properties"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-26"&gt;                    &lt;span class="dt"&gt;"street"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-27"&gt;                    &lt;span class="dt"&gt;"city"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-28"&gt;                    &lt;span class="dt"&gt;"state"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-29"&gt;                    &lt;span class="dt"&gt;"zip"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-30"&gt;                &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-31"&gt;                &lt;span class="dt"&gt;"required"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="ot"&gt;[&lt;/span&gt;&lt;span class="st"&gt;"street"&lt;/span&gt;&lt;span class="ot"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"city"&lt;/span&gt;&lt;span class="ot"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"state"&lt;/span&gt;&lt;span class="ot"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"zip"&lt;/span&gt;&lt;span class="ot"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-32"&gt;            &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-33"&gt;        &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-34"&gt;    &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-35"&gt;&lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id="example-using-an-array-type"&gt;5.3. Example: Using an Array Type&lt;/h3&gt;
&lt;p&gt;This example shows how to declare an array of strings, which is not much different from defining an object:&lt;/p&gt;
&lt;div id="cb9" class="sourceCode"&gt;
&lt;pre class="sourceCode json"&gt;&lt;code class="sourceCode json"&gt;&lt;span id="cb9-1"&gt;&lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-2"&gt;    &lt;span class="dt"&gt;"$schema"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"https://json-structure.org/meta/core/v0/#"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-3"&gt;    &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"array"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-4"&gt;    &lt;span class="dt"&gt;"items"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-5"&gt;&lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can also declare an array of a locally declared compound type, but you can not reference the type from elsewhere in the schema:&lt;/p&gt;
&lt;div id="cb10" class="sourceCode"&gt;
&lt;pre class="sourceCode json"&gt;&lt;code class="sourceCode json"&gt;&lt;span id="cb10-1"&gt;&lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-2"&gt;    &lt;span class="dt"&gt;"$schema"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"https://json-structure.org/meta/core/v0/#"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-3"&gt;    &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"array"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-4"&gt;    &lt;span class="dt"&gt;"items"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-5"&gt;        &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"object"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-6"&gt;        &lt;span class="dt"&gt;"properties"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-7"&gt;            &lt;span class="dt"&gt;"firstName"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-8"&gt;            &lt;span class="dt"&gt;"lastName"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-9"&gt;            &lt;span class="dt"&gt;"dateOfBirth"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"date"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-10"&gt;        &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-11"&gt;        &lt;span class="dt"&gt;"required"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="ot"&gt;[&lt;/span&gt;&lt;span class="st"&gt;"firstName"&lt;/span&gt;&lt;span class="ot"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"lastName"&lt;/span&gt;&lt;span class="ot"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-12"&gt;    &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-13"&gt;&lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;To declare an array of a reusable type, you can use the &lt;code&gt;$ref&lt;/code&gt; keyword:&lt;/p&gt;
&lt;div id="cb11" class="sourceCode"&gt;
&lt;pre class="sourceCode json"&gt;&lt;code class="sourceCode json"&gt;&lt;span id="cb11-1"&gt;&lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-2"&gt;    &lt;span class="dt"&gt;"$schema"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"https://json-structure.org/meta/core/v0/#"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-3"&gt;    &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"array"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-4"&gt;    &lt;span class="dt"&gt;"items"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt; &lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"$ref"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"#/definitions/Person"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-5"&gt;    &lt;span class="dt"&gt;"definitions"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-6"&gt;        &lt;span class="dt"&gt;"Person"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-7"&gt;            &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"object"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-8"&gt;            &lt;span class="dt"&gt;"name"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"Person"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-9"&gt;            &lt;span class="dt"&gt;"properties"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-10"&gt;                &lt;span class="dt"&gt;"firstName"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-11"&gt;                &lt;span class="dt"&gt;"lastName"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-12"&gt;                &lt;span class="dt"&gt;"dateOfBirth"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"date"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-13"&gt;            &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-14"&gt;            &lt;span class="dt"&gt;"required"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="ot"&gt;[&lt;/span&gt;&lt;span class="st"&gt;"firstName"&lt;/span&gt;&lt;span class="ot"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"lastName"&lt;/span&gt;&lt;span class="ot"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-15"&gt;        &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-16"&gt;    &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-17"&gt;&lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id="example-declaring-maps"&gt;5.4. Example: Declaring Maps&lt;/h3&gt;
&lt;p&gt;This example shows how to declare a map of strings to &lt;code&gt;Color&lt;/code&gt; objects:&lt;/p&gt;
&lt;div id="cb12" class="sourceCode"&gt;
&lt;pre class="sourceCode json"&gt;&lt;code class="sourceCode json"&gt;&lt;span id="cb12-1"&gt;&lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-2"&gt;    &lt;span class="dt"&gt;"$schema"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"https://json-structure.org/meta/core/v0/#"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-3"&gt;    &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"map"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-4"&gt;    &lt;span class="dt"&gt;"values"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"$ref"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"#/definitions/Color"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-5"&gt;    &lt;span class="dt"&gt;"definitions"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-6"&gt;        &lt;span class="dt"&gt;"Color"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-7"&gt;            &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"object"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-8"&gt;            &lt;span class="dt"&gt;"name"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"Color"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-9"&gt;            &lt;span class="dt"&gt;"properties"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-10"&gt;                &lt;span class="dt"&gt;"red"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"int32"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-11"&gt;                &lt;span class="dt"&gt;"green"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"int32"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-12"&gt;                &lt;span class="dt"&gt;"blue"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"int32"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-13"&gt;            &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-14"&gt;            &lt;span class="dt"&gt;"required"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="ot"&gt;[&lt;/span&gt;&lt;span class="st"&gt;"red"&lt;/span&gt;&lt;span class="ot"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"green"&lt;/span&gt;&lt;span class="ot"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"blue"&lt;/span&gt;&lt;span class="ot"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-15"&gt;        &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-16"&gt;    &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-17"&gt;&lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Instance data for this schema might look like this:&lt;/p&gt;
&lt;div id="cb13" class="sourceCode"&gt;
&lt;pre class="sourceCode json"&gt;&lt;code class="sourceCode json"&gt;&lt;span id="cb13-1"&gt;&lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-2"&gt;    &lt;span class="dt"&gt;"rose"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"red"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="dv"&gt;255&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;"green"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;"blue"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-3"&gt;    &lt;span class="dt"&gt;"sky"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"red"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;"green"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="dv"&gt;191&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;"blue"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="dv"&gt;255&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-4"&gt;    &lt;span class="dt"&gt;"grass"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"red"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;"green"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="dv"&gt;128&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;"blue"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-5"&gt;    &lt;span class="dt"&gt;"sun"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"red"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="dv"&gt;255&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;"green"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="dv"&gt;215&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;"blue"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-6"&gt;    &lt;span class="dt"&gt;"cloud"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"red"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="dv"&gt;255&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;"green"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="dv"&gt;255&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;"blue"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="dv"&gt;255&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-7"&gt;    &lt;span class="dt"&gt;"moon"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"red"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="dv"&gt;192&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;"green"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="dv"&gt;192&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;"blue"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="dv"&gt;192&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-8"&gt;&lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id="example-declaring-sets"&gt;5.5. Example: Declaring Sets&lt;/h3&gt;
&lt;p&gt;This example shows how to declare a set of strings:&lt;/p&gt;
&lt;div id="cb14" class="sourceCode"&gt;
&lt;pre class="sourceCode json"&gt;&lt;code class="sourceCode json"&gt;&lt;span id="cb14-1"&gt;&lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb14-2"&gt;    &lt;span class="dt"&gt;"$schema"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"https://json-structure.org/meta/core/v0/#"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb14-3"&gt;    &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"set"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb14-4"&gt;    &lt;span class="dt"&gt;"items"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb14-5"&gt;&lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Sets differ from arrays in that they are unordered and contain only unique elements. The schema above would match the following instance data:&lt;/p&gt;
&lt;div id="cb15" class="sourceCode"&gt;
&lt;pre class="sourceCode json"&gt;&lt;code class="sourceCode json"&gt;&lt;span id="cb15-1"&gt;&lt;span class="ot"&gt;[&lt;/span&gt;&lt;span class="st"&gt;"apple"&lt;/span&gt;&lt;span class="ot"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"banana"&lt;/span&gt;&lt;span class="ot"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"cherry"&lt;/span&gt;&lt;span class="ot"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id="example-declaring-tuples"&gt;5.6. Example: Declaring Tuples&lt;/h3&gt;
&lt;p&gt;Tuples are fixed-length arrays with named elements, declared via the &lt;code&gt;tuple&lt;/code&gt; keyword.&lt;/p&gt;
&lt;div id="cb16" class="sourceCode"&gt;
&lt;pre class="sourceCode json"&gt;&lt;code class="sourceCode json"&gt;&lt;span id="cb16-1"&gt;&lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-2"&gt;    &lt;span class="dt"&gt;"$schema"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"https://json-structure.org/meta/core/v0/#"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-3"&gt;    &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"tuple"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-4"&gt;    &lt;span class="dt"&gt;"name"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"PersonTuple"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-5"&gt;    &lt;span class="dt"&gt;"properties"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-6"&gt;        &lt;span class="dt"&gt;"firstName"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-7"&gt;        &lt;span class="dt"&gt;"age"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt;       &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"int32"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-8"&gt;    &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-9"&gt;    &lt;span class="dt"&gt;"tuple"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="ot"&gt;[&lt;/span&gt;&lt;span class="st"&gt;"firstName"&lt;/span&gt;&lt;span class="ot"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"age"&lt;/span&gt;&lt;span class="ot"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-10"&gt;&lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;An instance of this tuple type:&lt;/p&gt;
&lt;div id="cb17" class="sourceCode"&gt;
&lt;pre class="sourceCode json"&gt;&lt;code class="sourceCode json"&gt;&lt;span id="cb17-1"&gt;&lt;span class="ot"&gt;[&lt;/span&gt;&lt;span class="st"&gt;"Alice"&lt;/span&gt;&lt;span class="ot"&gt;,&lt;/span&gt; &lt;span class="dv"&gt;30&lt;/span&gt;&lt;span class="ot"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id="example-declaring-choice-types"&gt;5.7. Example: Declaring Choice Types&lt;/h3&gt;
&lt;p&gt;Choice types define discriminated unions via the &lt;code&gt;choice&lt;/code&gt; keyword. Two forms are supported:&lt;/p&gt;
&lt;h3 id="tagged-unions"&gt;5.8. Tagged Unions&lt;/h3&gt;
&lt;p&gt;Tagged unions represent the selected type as a single-property object:&lt;/p&gt;
&lt;div id="cb18" class="sourceCode"&gt;
&lt;pre class="sourceCode json"&gt;&lt;code class="sourceCode json"&gt;&lt;span id="cb18-1"&gt;&lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-2"&gt;    &lt;span class="dt"&gt;"$schema"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"https://json-structure.org/meta/core/v0/#"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-3"&gt;    &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"choice"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-4"&gt;    &lt;span class="dt"&gt;"name"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"StringOrNumber"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-5"&gt;    &lt;span class="dt"&gt;"choices"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-6"&gt;        &lt;span class="dt"&gt;"string"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-7"&gt;        &lt;span class="dt"&gt;"int32"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt;  &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"int32"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-8"&gt;    &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-9"&gt;&lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Valid instances:&lt;/p&gt;
&lt;div id="cb19" class="sourceCode"&gt;
&lt;pre class="sourceCode json"&gt;&lt;code class="sourceCode json"&gt;&lt;span id="cb19-1"&gt;&lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"string"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"Hello"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-2"&gt;&lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"int32"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt;  &lt;span class="dv"&gt;42&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id="inline-unions"&gt;5.9. Inline Unions&lt;/h3&gt;
&lt;p&gt;Inline unions extend a common abstract base type and use a selector property:&lt;/p&gt;
&lt;div id="cb20" class="sourceCode"&gt;
&lt;pre class="sourceCode json"&gt;&lt;code class="sourceCode json"&gt;&lt;span id="cb20-1"&gt;&lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-2"&gt;    &lt;span class="dt"&gt;"$schema"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"https://json-structure.org/meta/core/v0/#"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-3"&gt;    &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"choice"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-4"&gt;    &lt;span class="dt"&gt;"name"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"AddressChoice"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-5"&gt;    &lt;span class="dt"&gt;"$extends"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"#/definitions/Address"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-6"&gt;    &lt;span class="dt"&gt;"selector"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"addressType"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-7"&gt;    &lt;span class="dt"&gt;"choices"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-8"&gt;        &lt;span class="dt"&gt;"StreetAddress"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt;     &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"$ref"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"#/definitions/StreetAddress"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-9"&gt;        &lt;span class="dt"&gt;"PostOfficeBoxAddress"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"$ref"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"#/definitions/PostOfficeBoxAddress"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-10"&gt;    &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-11"&gt;    &lt;span class="dt"&gt;"definitions"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-12"&gt;        &lt;span class="dt"&gt;"Address"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-13"&gt;            &lt;span class="dt"&gt;"abstract"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-14"&gt;            &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"object"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-15"&gt;            &lt;span class="dt"&gt;"properties"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-16"&gt;                &lt;span class="dt"&gt;"city"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-17"&gt;                &lt;span class="dt"&gt;"state"&lt;/span&gt;&lt;span class="fu"&gt;:{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-18"&gt;                &lt;span class="dt"&gt;"zip"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt;  &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-19"&gt;            &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-20"&gt;        &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-21"&gt;        &lt;span class="dt"&gt;"StreetAddress"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-22"&gt;            &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"object"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-23"&gt;            &lt;span class="dt"&gt;"$extends"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"#/definitions/Address"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-24"&gt;            &lt;span class="dt"&gt;"properties"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"street"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-25"&gt;        &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-26"&gt;        &lt;span class="dt"&gt;"PostOfficeBoxAddress"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-27"&gt;            &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"object"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-28"&gt;            &lt;span class="dt"&gt;"$extends"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"#/definitions/Address"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-29"&gt;            &lt;span class="dt"&gt;"properties"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"poBox"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-30"&gt;        &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-31"&gt;    &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-32"&gt;&lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Instance of this inline union:&lt;/p&gt;
&lt;div id="cb21" class="sourceCode"&gt;
&lt;pre class="sourceCode json"&gt;&lt;code class="sourceCode json"&gt;&lt;span id="cb21-1"&gt;&lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb21-2"&gt;    &lt;span class="dt"&gt;"addressType"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"StreetAddress"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb21-3"&gt;    &lt;span class="dt"&gt;"street"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt;      &lt;span class="st"&gt;"123 Main St"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb21-4"&gt;    &lt;span class="dt"&gt;"city"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt;        &lt;span class="st"&gt;"AnyCity"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb21-5"&gt;    &lt;span class="dt"&gt;"state"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt;       &lt;span class="st"&gt;"AS"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb21-6"&gt;    &lt;span class="dt"&gt;"zip"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt;         &lt;span class="st"&gt;"11111"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb21-7"&gt;&lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id="using-companion-specifications"&gt;6. Using Companion Specifications&lt;/h2&gt;
&lt;p&gt;The JSON Structure Core specification is designed to be extensible through companion specifications that provide additional features and capabilities.&lt;/p&gt;
&lt;p&gt;The extended schema that includes all companion specifications is identified by the &lt;code&gt;https://json-structure.org/meta/extended/v0&lt;/code&gt; URI. Each companion specification is identified by a unique identifier that can be used in the &lt;code&gt;$uses&lt;/code&gt; attribute to activate the companion specification for the schema document.&lt;/p&gt;
&lt;p&gt;The feature identifiers for the companion specifications are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;JSONStructureAlternateNames&lt;/code&gt;: Alternate names and descriptions for properties and types.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JSONStructureUnits&lt;/code&gt;: Symbols, scientific units, and currencies for numeric properties.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JSONStructureImports&lt;/code&gt;: Importing types from other schema documents.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JSONStructureValidation&lt;/code&gt;: Validation rules for JSON data.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JSONStructureConditionalComposition&lt;/code&gt;: Conditional composition and validation rules.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="example-using-the-altnames-keyword"&gt;6.1. Example: Using the &lt;code&gt;altnames&lt;/code&gt; Keyword&lt;/h3&gt;
&lt;p&gt;The &lt;a href="https://github.com/json-structure/alternate-names"&gt;JSON Structure Alternate Names and Descriptions&lt;/a&gt; companion specification introduces the &lt;code&gt;altnames&lt;/code&gt; keyword to provide alternate names for properties and types. Alternate names provide additional mappings that schema processors may use for encoding, decoding, or user interface display.&lt;/p&gt;
&lt;p&gt;Here is an example of how to use the &lt;code&gt;altnames&lt;/code&gt; keyword:&lt;/p&gt;
&lt;div id="cb22" class="sourceCode"&gt;
&lt;pre class="sourceCode json"&gt;&lt;code class="sourceCode json"&gt;&lt;span id="cb22-1"&gt;&lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-2"&gt;    &lt;span class="dt"&gt;"$schema"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"https://json-structure.org/meta/extended/v0/#"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-3"&gt;    &lt;span class="dt"&gt;"$uses"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="ot"&gt;[&lt;/span&gt;&lt;span class="st"&gt;"JSONStructureAlternateNames"&lt;/span&gt;&lt;span class="ot"&gt;]&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-4"&gt;    &lt;span class="dt"&gt;"Person"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-5"&gt;        &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"object"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-6"&gt;        &lt;span class="dt"&gt;"altnames"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-7"&gt;            &lt;span class="dt"&gt;"json"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"person_data"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-8"&gt;            &lt;span class="dt"&gt;"lang:en"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"Person"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-9"&gt;            &lt;span class="dt"&gt;"lang:de"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"Person"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-10"&gt;        &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-11"&gt;        &lt;span class="dt"&gt;"properties"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-12"&gt;            &lt;span class="dt"&gt;"firstName"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-13"&gt;                &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-14"&gt;                &lt;span class="dt"&gt;"altnames"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-15"&gt;                    &lt;span class="dt"&gt;"json"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"first_name"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-16"&gt;                    &lt;span class="dt"&gt;"lang:en"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"First Name"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-17"&gt;                    &lt;span class="dt"&gt;"lang:de"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"Vorname"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-18"&gt;                &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-19"&gt;            &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-20"&gt;            &lt;span class="dt"&gt;"lastName"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-21"&gt;                &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-22"&gt;                &lt;span class="dt"&gt;"altnames"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-23"&gt;                    &lt;span class="dt"&gt;"json"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"last_name"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-24"&gt;                    &lt;span class="dt"&gt;"lang:en"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"Last Name"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-25"&gt;                    &lt;span class="dt"&gt;"lang:de"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"Nachname"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-26"&gt;                &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-27"&gt;            &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-28"&gt;        &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-29"&gt;        &lt;span class="dt"&gt;"required"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="ot"&gt;[&lt;/span&gt;&lt;span class="st"&gt;"firstName"&lt;/span&gt;&lt;span class="ot"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"lastName"&lt;/span&gt;&lt;span class="ot"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-30"&gt;    &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-31"&gt;&lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Each named type or property in the schema has been given an &lt;code&gt;altnames&lt;/code&gt; attribute that provides alternate names for the type or property.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;json&lt;/code&gt; key is used to specify alternate names for JSON encoding, meaning that if the schema is used to encode or decode JSON data, the alternate key MUST be used instead of the name in the schema.&lt;/p&gt;
&lt;p&gt;Keys beginning with &lt;code&gt;lang:&lt;/code&gt; are reserved for providing localized alternate names that can be used for user interface display. Additional keys can be used for custom purposes, subject to no conflicts with reserved keys or prefixes.&lt;/p&gt;
&lt;h3 id="example-using-the-altenums-keyword"&gt;6.2. Example: Using the &lt;code&gt;altenums&lt;/code&gt; Keyword&lt;/h3&gt;
&lt;p&gt;The &lt;a href="https://github.com/json-structure/alternate-names"&gt;JSON Structure Alternate Enumerations&lt;/a&gt; companion specification introduces the &lt;code&gt;altenums&lt;/code&gt; keyword to provide alternative representations for enumeration values defined by a type using the &lt;code&gt;enum&lt;/code&gt; keyword. Alternate symbols allow schema authors to map internal enum values to external codes or localized display symbols.&lt;/p&gt;
&lt;p&gt;Here is an example of how to use the &lt;code&gt;altenums&lt;/code&gt; keyword:&lt;/p&gt;
&lt;div id="cb23" class="sourceCode"&gt;
&lt;pre class="sourceCode json"&gt;&lt;code class="sourceCode json"&gt;&lt;span id="cb23-1"&gt;&lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-2"&gt;    &lt;span class="dt"&gt;"$schema"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"https://json-structure.org/meta/extended/v0/#"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-3"&gt;    &lt;span class="dt"&gt;"$uses"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="ot"&gt;[&lt;/span&gt;&lt;span class="st"&gt;"JSONStructureAlternateNames"&lt;/span&gt;&lt;span class="ot"&gt;]&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-4"&gt;    &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"object"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-5"&gt;    &lt;span class="dt"&gt;"name"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"Color"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-6"&gt;    &lt;span class="dt"&gt;"properties"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-7"&gt;        &lt;span class="dt"&gt;"name"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt; &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-8"&gt;        &lt;span class="dt"&gt;"value"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;/span&gt;
&lt;span id="cb23-9"&gt;            &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"string"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt; &lt;/span&gt;
&lt;span id="cb23-10"&gt;            &lt;span class="dt"&gt;"enum"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="ot"&gt;[&lt;/span&gt;&lt;span class="st"&gt;"red"&lt;/span&gt;&lt;span class="ot"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"green"&lt;/span&gt;&lt;span class="ot"&gt;,&lt;/span&gt; &lt;span class="st"&gt;"blue"&lt;/span&gt;&lt;span class="ot"&gt;]&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-11"&gt;            &lt;span class="dt"&gt;"altenums"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-12"&gt;                &lt;span class="dt"&gt;"lang:en"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-13"&gt;                    &lt;span class="dt"&gt;"red"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"Red"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-14"&gt;                    &lt;span class="dt"&gt;"green"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"Green"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-15"&gt;                    &lt;span class="dt"&gt;"blue"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"Blue"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-16"&gt;                &lt;span class="fu"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-17"&gt;                &lt;span class="dt"&gt;"lang:de"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-18"&gt;                    &lt;span class="dt"&gt;"red"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"Rot"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-19"&gt;                    &lt;span class="dt"&gt;"green"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"Gr&amp;uuml;n"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-20"&gt;                    &lt;span class="dt"&gt;"blue"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"Blau"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-21"&gt;                &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-22"&gt;            &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-23"&gt;        &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-24"&gt;    &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-25"&gt;&lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In this example, the &lt;code&gt;value&lt;/code&gt; property has an &lt;code&gt;enum&lt;/code&gt; attribute that defines the possible values for the property. The &lt;code&gt;altenums&lt;/code&gt; attribute provides alternative names for each enumeration value. The &lt;code&gt;lang:en&lt;/code&gt; key provides English names for the enumeration values, and the &lt;code&gt;lang:de&lt;/code&gt; key provides German names.&lt;/p&gt;
&lt;h3 id="example-using-the-unit-keyword"&gt;6.3. Example: Using the &lt;code&gt;unit&lt;/code&gt; Keyword&lt;/h3&gt;
&lt;p&gt;The &lt;a href="https://github.com/json-structure/units"&gt;JSON Structure Symbols, Scientific Units, and Currencies&lt;/a&gt; companion specification introduces the &lt;code&gt;unit&lt;/code&gt; keyword to provide a standard way to specify the unit of measurement for numeric properties. The &lt;code&gt;unit&lt;/code&gt; keyword allows schema authors to specify the unit of measurement for numeric properties and provides a standard way to encode and decode numeric values with units.&lt;/p&gt;
&lt;p&gt;Here is an example of how to use the &lt;code&gt;unit&lt;/code&gt; keyword:&lt;/p&gt;
&lt;div id="cb24" class="sourceCode"&gt;
&lt;pre class="sourceCode json"&gt;&lt;code class="sourceCode json"&gt;&lt;span id="cb24-1"&gt;&lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-2"&gt;    &lt;span class="dt"&gt;"$schema"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"https://json-structure.org/meta/extended/v0/#"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-3"&gt;    &lt;span class="dt"&gt;"$uses"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="ot"&gt;[&lt;/span&gt;&lt;span class="st"&gt;"JSONStructureUnits"&lt;/span&gt;&lt;span class="ot"&gt;]&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-4"&gt;    &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"object"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-5"&gt;    &lt;span class="dt"&gt;"name"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"Pressure"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-6"&gt;    &lt;span class="dt"&gt;"properties"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-7"&gt;        &lt;span class="dt"&gt;"value"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"number"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;"unit"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"Pa"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-8"&gt;    &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-9"&gt;&lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In this example, the &lt;code&gt;value&lt;/code&gt; property has a &lt;code&gt;unit&lt;/code&gt; attribute that specifies the unit of measurement for the property. The unit of measurement is specified as a string value. In this case, the unit of measurement is &amp;ldquo;Pa&amp;rdquo; for Pascals.&lt;/p&gt;
&lt;h3 id="example-using-the-currency-keyword"&gt;6.4. Example: Using the &lt;code&gt;currency&lt;/code&gt; Keyword&lt;/h3&gt;
&lt;p&gt;The &lt;a href="https://github.com/json-structure/units"&gt;JSON Structure Symbols, Scientific Units, and Currencies&lt;/a&gt; companion specification also introduces the &lt;code&gt;currency&lt;/code&gt; keyword to provide a standard way to specify the currency for monetary properties. The &lt;code&gt;currency&lt;/code&gt; keyword allows schema authors to specify the currency for monetary properties and provides a standard way to encode and decode monetary values with currencies.&lt;/p&gt;
&lt;p&gt;Here is an example of how to use the &lt;code&gt;currency&lt;/code&gt; keyword:&lt;/p&gt;
&lt;div id="cb25" class="sourceCode"&gt;
&lt;pre class="sourceCode json"&gt;&lt;code class="sourceCode json"&gt;&lt;span id="cb25-1"&gt;&lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb25-2"&gt;    &lt;span class="dt"&gt;"$schema"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"https://json-structure.org/meta/extended/v0/#"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb25-3"&gt;    &lt;span class="dt"&gt;"$uses"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="ot"&gt;[&lt;/span&gt;&lt;span class="st"&gt;"JSONStructureUnits"&lt;/span&gt;&lt;span class="ot"&gt;]&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb25-4"&gt;    &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"object"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb25-5"&gt;    &lt;span class="dt"&gt;"name"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"Price"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb25-6"&gt;    &lt;span class="dt"&gt;"properties"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb25-7"&gt;        &lt;span class="dt"&gt;"value"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;{&lt;/span&gt; &lt;span class="dt"&gt;"type"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"decimal"&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;"precision"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="dv"&gt;20&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;"scale"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt;&lt;span class="fu"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;"currency"&lt;/span&gt;&lt;span class="fu"&gt;:&lt;/span&gt; &lt;span class="st"&gt;"USD"&lt;/span&gt; &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb25-8"&gt;    &lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb25-9"&gt;&lt;span class="fu"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In this example, the &lt;code&gt;value&lt;/code&gt; property has a &lt;code&gt;currency&lt;/code&gt; attribute that specifies the currency for the property. The currency is specified as a string value. In this case, the currency is &amp;ldquo;USD&amp;rdquo; for US Dollars.&lt;/p&gt;
&lt;h2 id="using-validation"&gt;7. Using Validation&lt;/h2&gt;
&lt;p&gt;The companion specifications for conditional composition and validation provide additional constructs for defining conditional validation rules and composing that resemble those found in prior versions of JSON Schema. However, those have been split out into optional extensions to keep the core schema language simple.&lt;/p&gt;
&lt;h3 id="example-using-conditional-composition"&gt;7.1. Example: Using Conditional Composition&lt;/h3&gt;
&lt;p&gt;The &lt;a href="https://github.com/json-structure/conditional-composition"&gt;JSON Structure Conditionals&lt;/a&gt; companion specification introduces conditional composition constructs for combining multiple schema definitions. In particular, this specification defines the semantics, syntax, and constraints for the keywords &lt;code&gt;allOf&lt;/code&gt;, &lt;code&gt;anyOf&lt;/code&gt;, &lt;code&gt;oneOf&lt;/code&gt;, and &lt;code&gt;not&lt;/code&gt;, as well as the &lt;code&gt;if&lt;/code&gt;/&lt;code&gt;then&lt;/code&gt;/&lt;code&gt;else&lt;/code&gt; conditional construct.&lt;/p&gt;
&lt;p&gt;The specification has several examples that show how to use the conditional composition keywords.&lt;/p&gt;
&lt;h3 id="example-using-validation-rules"&gt;7.2. Example: Using Validation Rules&lt;/h3&gt;
&lt;p&gt;The &lt;a href="https://github.com/json-structure/validation"&gt;JSON Structure Validation&lt;/a&gt; companion specification introduces additional validation rules for JSON data.&lt;/p&gt;
&lt;h2 id="sdk-and-tooling-ecosystem"&gt;8. SDK and Tooling Ecosystem&lt;/h2&gt;
&lt;p&gt;A schema language without tooling remains theoretical. For developers to adopt JSON Structure, they need to be able to tell whether schemas are valid, whether documents conform to a given schema, and they need to be able to turn schemas into data structures they can code against.&lt;/p&gt;
&lt;p&gt;The JSON Structure SDKs provide native implementations for schema validation (is this schema well-formed?) and instance validation (does this JSON document conform to this schema?) across all major programming languages:&lt;/p&gt;
&lt;table&gt;&lt;colgroup&gt; &lt;col style="width: 37%;"&gt; &lt;col style="width: 33%;"&gt; &lt;col style="width: 29%;"&gt; &lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Language&lt;/th&gt;
&lt;th&gt;Package&lt;/th&gt;
&lt;th&gt;Install&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;&lt;a href="https://pypi.org/project/json-structure/"&gt;json-structure&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pip install json-structure&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;.NET/C#&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.nuget.org/packages/JsonStructure/"&gt;JsonStructure&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;dotnet add package JsonStructure&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Java&lt;/td&gt;
&lt;td&gt;&lt;a href="https://central.sonatype.com/artifact/io.json-structure/json-structure"&gt;json-structure&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Maven Central&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TypeScript/JS&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.npmjs.com/package/@aspect/json-structure"&gt;&lt;span class="citation" data-cites="aspect/json-structure"&gt;@aspect/json-structure&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;npm install @aspect/json-structure&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/json-structure/sdk"&gt;github.com/json-structure/sdk/go&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go get github.com/json-structure/sdk/go&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rust&lt;/td&gt;
&lt;td&gt;&lt;a href="https://crates.io/crates/json-structure"&gt;json-structure&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;cargo add json-structure&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C/C++ (C99)&lt;/td&gt;
&lt;td&gt;Build from repo&lt;/td&gt;
&lt;td&gt;CMake&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For languages with runtime introspection (Java, .NET/C#, Python), the SDKs also include schema exporters that produce JSON Structure schemas from existing runtime data structures&amp;mdash;useful for adopting JSON Structure incrementally in existing codebases.&lt;/p&gt;
&lt;p&gt;The SDK repository is at &lt;a class="uri" href="https://github.com/json-structure/sdk"&gt;https://github.com/json-structure/sdk&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="visual-studio-code-extension"&gt;9. Visual Studio Code Extension&lt;/h2&gt;
&lt;p&gt;The JSON Structure extension for Visual Studio Code, built on the TypeScript SDK, provides a first-class editing experience for &lt;code&gt;.struct.json&lt;/code&gt; schema files:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Schema validation&lt;/strong&gt;: Real-time feedback on schema syntax and structure&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Instance validation&lt;/strong&gt;: Validate JSON documents against JSON Structure schemas&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IntelliSense&lt;/strong&gt;: Auto-completion for keywords, types, and references&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hover documentation&lt;/strong&gt;: Contextual help for all schema elements&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Install from the VS Code Marketplace or search for &amp;ldquo;JSON Structure&amp;rdquo; in the Extensions view.&lt;/p&gt;
&lt;h2 id="structurize-schema-conversion-and-code-generation"&gt;10. Structurize: Schema Conversion and Code Generation&lt;/h2&gt;
&lt;p&gt;The &lt;strong&gt;Structurize&lt;/strong&gt; tool (a persona of the Avrotize tool) enables robust, predictable conversion between numerous schema formats and generates code for multiple target languages. JSON Structure serves as a second &amp;ldquo;pivot&amp;rdquo; schema model for this tool, meaning you can convert &lt;em&gt;from&lt;/em&gt; many formats &lt;em&gt;to&lt;/em&gt; JSON Structure, and &lt;em&gt;from&lt;/em&gt; JSON Structure &lt;em&gt;to&lt;/em&gt; many targets&amp;mdash;preserving the full richness of the type model.&lt;/p&gt;
&lt;h3 id="installation"&gt;Installation&lt;/h3&gt;
&lt;div id="cb26" class="sourceCode"&gt;
&lt;pre class="sourceCode bash"&gt;&lt;code class="sourceCode bash"&gt;&lt;span id="cb26-1"&gt;&lt;span class="ex"&gt;pip&lt;/span&gt; install structurize&lt;/span&gt;
&lt;span id="cb26-2"&gt;&lt;span class="co"&gt;# or&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb26-3"&gt;&lt;span class="ex"&gt;pip&lt;/span&gt; install avrotize&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;For the moment, the tools have an identical set of commands, but they may eventually be split. There will eventually be a bundled installer (as for the Azure CLI) so that you don&amp;rsquo;t need Python preinstalled.&lt;/p&gt;
&lt;h3 id="example-conversions"&gt;Example Conversions&lt;/h3&gt;
&lt;table&gt;&lt;colgroup&gt; &lt;col style="width: 31%;"&gt; &lt;col style="width: 26%;"&gt; &lt;col style="width: 42%;"&gt; &lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;From&lt;/th&gt;
&lt;th&gt;To&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;JSON Structure&lt;/td&gt;
&lt;td&gt;C#&lt;/td&gt;
&lt;td&gt;&lt;code&gt;structurize jsonstruct2cs schema.struct.json --out Models.cs&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JSON Structure&lt;/td&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;&lt;code&gt;structurize jsonstruct2py schema.struct.json --out models.py&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JSON Structure&lt;/td&gt;
&lt;td&gt;Java&lt;/td&gt;
&lt;td&gt;&lt;code&gt;structurize jsonstruct2java schema.struct.json --out-dir ./src&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JSON Structure&lt;/td&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;td&gt;&lt;code&gt;structurize jsonstruct2go schema.struct.json --out models.go&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JSON Structure&lt;/td&gt;
&lt;td&gt;C++&lt;/td&gt;
&lt;td&gt;&lt;code&gt;structurize jsonstruct2cpp schema.struct.json --out models.hpp&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JSON Structure&lt;/td&gt;
&lt;td&gt;Protobuf&lt;/td&gt;
&lt;td&gt;&lt;code&gt;structurize jsonstruct2proto schema.struct.json --out schema.proto&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JSON Structure&lt;/td&gt;
&lt;td&gt;PostgreSQL&lt;/td&gt;
&lt;td&gt;&lt;code&gt;structurize jsonstruct2pgsql schema.struct.json --out schema.sql&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;There are many more database dialects and target formats available. The full docs are in the &lt;a href="https://github.com/clemensv/avrotize"&gt;Avrotize repo README&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="chaining-conversions"&gt;Chaining Conversions&lt;/h3&gt;
&lt;p&gt;The tool is built such that you can pipe conversions, so you could go from ASN.1 via Avro to JSON Structure to C# with minimal loss of type info:&lt;/p&gt;
&lt;div id="cb27" class="sourceCode"&gt;
&lt;pre class="sourceCode bash"&gt;&lt;code class="sourceCode bash"&gt;&lt;span id="cb27-1"&gt;&lt;span class="co"&gt;# ASN.1 &amp;rarr; Avro &amp;rarr; JSON Structure &amp;rarr; C#&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb27-2"&gt;&lt;span class="ex"&gt;structurize&lt;/span&gt; asn2avro schema.asn &lt;span class="kw"&gt;|&lt;/span&gt; &lt;span class="ex"&gt;structurize&lt;/span&gt; avro2jsonstruct &lt;span class="kw"&gt;|&lt;/span&gt; &lt;span class="ex"&gt;structurize&lt;/span&gt; jsonstruct2cs &lt;span class="at"&gt;--out&lt;/span&gt; Models.cs&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id="resources-and-next-steps"&gt;11. Resources and Next Steps&lt;/h2&gt;
&lt;h3 id="specifications-ietf-internet-drafts"&gt;Specifications (IETF Internet Drafts)&lt;/h3&gt;
&lt;p&gt;All JSON Structure specifications are published as IETF Internet Drafts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/json-structure/core"&gt;JSON Structure Core&lt;/a&gt; - The core schema language&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/json-structure/import"&gt;JSON Structure Import&lt;/a&gt; - Importing types from other documents&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/json-structure/alternate-names"&gt;JSON Structure Alternate Names&lt;/a&gt; - Alternate names and i18n&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/json-structure/units"&gt;JSON Structure Units&lt;/a&gt; - Symbols, scientific units, currencies&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/json-structure/validation"&gt;JSON Structure Validation&lt;/a&gt; - Validation constraints&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/json-structure/conditional-composition"&gt;JSON Structure Conditional Composition&lt;/a&gt; - allOf, anyOf, oneOf, if/then/else&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All drafts are available at: &lt;a class="uri" href="https://datatracker.ietf.org/doc/search?name=draft-vasters-json-structure"&gt;https://datatracker.ietf.org/doc/search?name=draft-vasters-json-structure&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="sdk-and-tools"&gt;SDK and Tools&lt;/h3&gt;
&lt;table&gt;&lt;colgroup&gt; &lt;col style="width: 62%;"&gt; &lt;col style="width: 37%;"&gt; &lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Resource&lt;/th&gt;
&lt;th&gt;Link&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SDK Repository&lt;/td&gt;
&lt;td&gt;&lt;a class="uri" href="https://github.com/json-structure/sdk"&gt;https://github.com/json-structure/sdk&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VS Code Extension&lt;/td&gt;
&lt;td&gt;Search &amp;ldquo;JSON Structure&amp;rdquo; in VS Code Marketplace&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Structurize/Avrotize&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pip install structurize&lt;/code&gt; or &lt;a class="uri" href="https://github.com/clemensv/avrotize"&gt;https://github.com/clemensv/avrotize&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="sample-schemas"&gt;Sample Schemas&lt;/h3&gt;
&lt;p&gt;The &lt;a href="https://vasters.com/clemens/samples/"&gt;samples&lt;/a&gt; folder in this repository contains working examples organized by specification:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;samples/core/&lt;/code&gt; - Core specification examples with validation scripts&lt;/li&gt;
&lt;li&gt;&lt;code&gt;samples/import/&lt;/code&gt; - Import specification examples&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="getting-started"&gt;Getting Started&lt;/h3&gt;
&lt;ol type="1"&gt;
&lt;li&gt;&lt;strong&gt;Install the VS Code extension&lt;/strong&gt; for editing support with validation and IntelliSense&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Install the SDK&lt;/strong&gt; for your language to validate schemas and instances programmatically&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Try the samples&lt;/strong&gt; to understand the schema patterns&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use Structurize&lt;/strong&gt; to convert existing schemas or generate code for your target language&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;&lt;img src="https://vasters.com/clemens/content/binary/Gemini_Generated_Image_kodl8bkodl8bkodl.png" border="0"&gt;&lt;/p&gt;&lt;/div&gt;</description></item><item><trackback:ping>https://vasters.com/clemens/feed/trackback/941d7362-6c30-40e3-b688-6d1b424747ff</trackback:ping><pingback:server>https://vasters.com/clemens/feed/pingback</pingback:server><pingback:target>https://vasters.com/clemens/post/941d7362-6c30-40e3-b688-6d1b424747ff</pingback:target><dc:creator /><title>Agent Autonomy</title><guid isPermaLink="false">https://vasters.com/clemens/post/941d7362-6c30-40e3-b688-6d1b424747ff</guid><link>https://vasters.com/clemens/2025/08/18/agent-autonomy</link><pubDate>Mon, 18 Aug 2025 12:10:16 GMT</pubDate><description>&lt;div&gt;&lt;p&gt;Autonomy is what makes AI agents reliable building blocks.&lt;br&gt;&lt;br&gt;It means an agent is a self-contained unit of management, deployment, and ownership that can operate independently while participating in a larger system. It controls its own state, evolves on its own schedule, and interacts with others only through well-defined contracts. It has its own lifecycle, its own operational envelope, and its own accountability boundaries.&lt;br&gt;&lt;br&gt;Sounds familiar? The principles of service orientation are alive and well and proven and will also apply to collaborative agents.&lt;br&gt;&lt;br&gt;Autonomy means:&lt;br&gt;- Owns its state and logic &amp;rarr; No shared DB tables, no shared caches, no hidden in-memory state tied to another agent&amp;rsquo;s runtime. If you want something, you ask through its defined interface.&lt;br&gt;- Runs on its own lifecycle and scaling plan &amp;rarr; Deploy, update, restart, or scale it without coordinating with others.&lt;br&gt;- Exposes clear RPC or messaging interfaces &amp;rarr; All interactions happen through an explicit, documented contract.&lt;br&gt;- Honors its contract &amp;rarr; Can be evolved internally without breaking external expectations.&lt;br&gt;&lt;br&gt;When agents have these properties, we can assemble collaborative processes the way we plug components into a system bus &amp;mdash; mixing humans, LLM-powered reasoning agents, and traditional services without tight coupling.&lt;br&gt;&lt;br&gt;Autonomy isn&amp;rsquo;t just an architectural preference &amp;mdash; it&amp;rsquo;s the foundation for resilience, scalability, and adaptability.&lt;br&gt;&lt;br&gt;It means:&lt;br&gt;- Agents can be developed by different teams.&lt;br&gt;- Deployed on different schedules.&lt;br&gt;- Governed by different owners.&lt;br&gt;- Still work together without friction.&lt;br&gt;- Failures stay contained.&lt;br&gt;- Upgrades don&amp;rsquo;t ripple across the network.&lt;br&gt;- New capabilities can be added without destabilizing what&amp;rsquo;s already running.&lt;br&gt;&lt;br&gt;Without autonomy, your &amp;ldquo;agent network&amp;rdquo; is just a fragile, distributed monolith &amp;mdash; every change is a negotiation, scaling breaks under load, and one bad actor can take the whole thing down.&lt;br&gt;&lt;br&gt;And it is essential for autonomous agents to also be temporally decoupled from others and to not immediately tie the reliability/availability of an agent to that of another. You achieve that by preferring asynchronous communication paths wherever feasible. Surround agents with moats of queues and embrace event-driven architecture for creating process observability.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img style="width: 100%;" src="https://vasters.com/clemens/content/binary/BCO.5874b218-880b-4f79-aaa5-2fc925dc8694.png" border="0"&gt;&lt;/p&gt;&lt;/div&gt;</description></item><item><trackback:ping>https://vasters.com/clemens/feed/trackback/97f0b6f7-a924-4216-ba68-61f6dc2df82e</trackback:ping><pingback:server>https://vasters.com/clemens/feed/pingback</pingback:server><pingback:target>https://vasters.com/clemens/post/97f0b6f7-a924-4216-ba68-61f6dc2df82e</pingback:target><dc:creator /><title>An Interface Design Test for Collaborative Agents</title><guid isPermaLink="false">https://vasters.com/clemens/post/97f0b6f7-a924-4216-ba68-61f6dc2df82e</guid><link>https://vasters.com/clemens/2025/08/18/an-interface-design-test-for-collaborative-agents</link><pubDate>Mon, 18 Aug 2025 08:21:30 GMT</pubDate><description>&lt;div&gt;&lt;p&gt;An "agent" is a participant in a collaboration that autonomously solves a given aspect of a problem in the context of a system. An agent can be implement by a deterministic software module, by a person (human-in-the-loop), or by an AI component (AI-in-the-loop). Some implementations may employ multiple of these at once or as fallback options.&amp;nbsp;&lt;br&gt;&lt;br&gt;I propose the following design test for the interfaces of collaborating agents, inspired by the &lt;a href="https://en.wikipedia.org/wiki/Turing_test" target="_blank" rel="noopener"&gt;Turing Test&lt;/a&gt;:&lt;/p&gt;
&lt;p style="padding-left: 40px;"&gt;&lt;em&gt;If you communicate through an I/O interface with an agent, and you cannot distinguish by the form of the I/O interface or its data flow shape or behavior or even its temporal behavior whether the agent is implemented by deterministic code, by AI-in-the-loop, by Human-in-the-loop, or by a federation of collaborating agents, then your interface design is correct.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The motivation of this test is that you will generally understand the problem you are trying to solve and you will understand what inputs you can provide and what outputs you expect, but you may not know what implementation choice ends up being the best for a problem once you consider cost and performance and accuracy and user satisfaction over time. Problems might not yet be solvable using AI but they will be in the future, or you might think that AI is the best choice now, but you may have to fall back to other options for some reason.&lt;/p&gt;
&lt;p&gt;One of the consequences from this test is that the interface must flow structured data and not an unstructured "natural language interface", which would require an LLM or a similar processor to break down the input for a deterministic implementation. Each agent must have a clear and well-defined input and output interface. Natural language input must be broken down to match that interface.&lt;/p&gt;
&lt;p&gt;&lt;img style="width: 100%;" src="https://vasters.com/clemens/content/binary/BCO.b266e1bc-2531-4104-948d-2fde2f5ce57a.png" border="0"&gt;&lt;/p&gt;&lt;/div&gt;</description></item><item xml:lang="en-us"><trackback:ping>https://vasters.com/clemens/feed/trackback/d8d17dea-17e4-4e20-af15-e64cf5661b8a</trackback:ping><pingback:server>https://vasters.com/clemens/feed/pingback</pingback:server><pingback:target>https://vasters.com/clemens/post/d8d17dea-17e4-4e20-af15-e64cf5661b8a</pingback:target><dc:creator /><title>CNCF xRegistry 1.0 RC1 - What. Why. What might be next.</title><guid isPermaLink="false">https://vasters.com/clemens/post/d8d17dea-17e4-4e20-af15-e64cf5661b8a</guid><link>https://vasters.com/clemens/2025/04/16/cncf-xregistry-10-rc1-what-why-what-might-be-next</link><pubDate>Wed, 16 Apr 2025 12:49:29 GMT</pubDate><description>&lt;div&gt;&lt;p&gt;&lt;img style="width: 100%;" src="https://vasters.com/clemens/content/binary/newJSONschema.jpeg" border="0"&gt;&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="2"&gt;Two weeks ago, during a very busy conference week that saw CNCF KubeCon, Hannover Messe, and FabCon all take place simultaneously, with me being in Hannover, the CNCF Serverless Working Group that I am part of, released the first release candidate of &lt;a href="https://xregistry.io/" data-href="https://xregistry.io"&gt;xRegistry&lt;/a&gt;. This is a significant milestone for the project, and I wanted to take a moment to share what xRegistry is, why it matters, and what&amp;rsquo;s next for the project.&lt;/p&gt;
&lt;h3 class="code-line" dir="auto" data-line="2"&gt;Origins&lt;/h3&gt;
&lt;p class="code-line" dir="auto" data-line="9"&gt;The xRegistry project is a sibling project of&amp;nbsp;&lt;a href="https://cloudevents.io/" data-href="https://cloudevents.io"&gt;CNCF CloudEvents&lt;/a&gt;, produced by the same working group and, for the most part, the same people.&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="13"&gt;After the CloudEvents 1.0 release in 2019, the working group vowed to avoid breaking changes and give CloudEvents time and stability for adoption. Since then, we've relased 1.0.1, 1.0.2 as "errata" releases with 1.0.3 being the current "work in progress" version for further corrections. None of those releases made any substantial changes to the core spec, but we've made some additions and a few tweaks in the attribute extensions and transport binding and event format areas.&lt;/p&gt;
&lt;h3 class="code-line" dir="auto" data-line="13"&gt;Observations&lt;/h3&gt;
&lt;p class="code-line" dir="auto" data-line="21"&gt;As folks were starting to implement CloudEvents in serious projects, we made a few observations:&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="24"&gt;First, the&amp;nbsp;&lt;code&gt;data&lt;/code&gt;&amp;nbsp;section of a CloudEvent generally contains structured data that is serialized in a specific encoding (JSON, XML, Avro, Protobuf, etc.). Some of these encodings require schema documents to be able to even understand the encoded data, as it is the case for Avro and Protobuf.&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="29"&gt;For the CloudEvents envelope, we had a formal binding and schema for Avro in the v1.0 release and added a Protobuf binding in the v1.0.1 release.&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="32"&gt;Since our goal for CloudEvents is to promote interoperability and vendor neutrality, the question quickly arose on how to enable applications to share schema documents for the data section of a CloudEvent if developers wanted to use one of these efficient and binary but schema-dependent encodings. Some schema registry products/projects were around at the time, but there were no vendor-neutral specifications or standards for them.&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="39"&gt;Second, we observed that when applications were raising CloudEvents, the way how those CloudEvents were made known to developers was generally through prose and examples in documentation. There was no formal, machine readable way to declare and document the shape of a CloudEvent: What is the&amp;nbsp;&lt;code&gt;type&lt;/code&gt;&amp;nbsp;value, what does the&amp;nbsp;&lt;code&gt;source&lt;/code&gt;&amp;nbsp;value look like, what are the required and optional standards and extension attributes for this specific event type, and what is the schema for the&amp;nbsp;&lt;code&gt;data&lt;/code&gt;&amp;nbsp;section?&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="47"&gt;Third, we heard that it would be very useful for developer tools to be able to know about event sources and sinks that exist in their ecosystem, so that applications can be built that can react to events from those sources and send events to those sinks.&lt;/p&gt;
&lt;h3 class="code-line" dir="auto" data-line="47"&gt;Explorations&lt;/h3&gt;
&lt;p class="code-line" dir="auto" data-line="52"&gt;As a result, we started some exploratory work in the working group on "schema registry" and "discovery". Mike Helmick from LinkedIn submitted a&amp;nbsp;&lt;a href="https://github.com/cloudevents/spec/pull/580" data-href="https://github.com/cloudevents/spec/pull/580"&gt;"Discovery API"&lt;/a&gt;&amp;nbsp;in March 2020. I proposed a&amp;nbsp;&lt;a href="https://github.com/cloudevents/spec/pull/625" data-href="https://github.com/cloudevents/spec/pull/625"&gt;"Schema registry API"&lt;/a&gt;&amp;nbsp;in May 2020.&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="58"&gt;After the chaos of the pandemic, we starts a sub-working group to make progress in that area and to explore the three aspects I mentioned above: How do I share schema? How do I catalog and declare events? How do I discover event sinks and sources?&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="63"&gt;As we made progress on this, we realized that these three sub-projects were so interdependent that it would be beneficial if these three registries could be, optionally, collocated behind a single API facade. We also realized that an API alone would not be sufficient, but that we would also want for the same metadata to be available in document format such that it could be exchanged or used to drive tools like code generators.&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="70"&gt;As we then worked on aligning the APIs, we found that we had a lot of commonalities across the three registries, and that we could actually build a single registry API that would be able to serve all three use cases, whereby the differences could be expressed in a lightweight configuration-model that the registry server could use to adapt the API to the specific use case.&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="76"&gt;Once we arrived at this conclusion, we also realized that we could use the same configuration model for any other metadata registry use case. Thus, the extensible registry, xRegistry, came into being.&lt;/p&gt;
&lt;h3 class="code-line" dir="auto" data-line="76"&gt;xRegistry&lt;/h3&gt;
&lt;p class="code-line" dir="auto" data-line="80"&gt;The&amp;nbsp;&lt;a href="https://github.com/xregistry/spec/blob/main/core/spec.md" data-href="https://github.com/xregistry/spec/blob/main/core/spec.md"&gt;core specification&lt;/a&gt;&amp;nbsp;of xRegistry describes a document format and a REST API that can be used to manage and interact with metadata registries. The core specification also defines the configuration model that allows to define the registry behavior and the specific sub-registry metadata content. If the&amp;nbsp;&lt;code&gt;hasdocument&lt;/code&gt;&amp;nbsp;model attribute is&amp;nbsp;&lt;code&gt;true&lt;/code&gt;&amp;nbsp;for a resource type, the registry acts as a document store with accompanying metadata. If the value is&amp;nbsp;&lt;code&gt;false&lt;/code&gt;, it's a pure structured data store.&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="88"&gt;A key principle across xRegistry is that all resources are managed inside of groups. A group is a logical collection of resources that can be used for organization and/or access control. It's possible to cross-reference resources between groups, such that one resource can logically occur in multiple groups.&lt;/p&gt;
&lt;p&gt;&lt;img style="height: 200px;" src="https://vasters.com/clemens/content/binary/xregistry-core.jpg" border="0"&gt;&lt;img style="height: 200px;" src="https://vasters.com/clemens/content/binary/xregistry-structure.jpg" border="0"&gt;&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="93"&gt;The&amp;nbsp;&lt;a href="https://github.com/xregistry/spec/blob/main/schema/spec.md" data-href="https://github.com/xregistry/spec/blob/main/schema/spec.md"&gt;schema&lt;/a&gt;&amp;nbsp;specification defines a sub-registry for serialization and validation schema documents. It enables the versioning model of xRegistry such that all versions of a schema document are kept in the registry and can be referenced by their version. The registry has a notion of a "default" schema version, which is the one that is returned when no version is specified. The registry is also able to maintain version lineage information and provides a compatibility policy mechanism that implementations can enforce.&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="102"&gt;The&amp;nbsp;&lt;a href="https://github.com/xregistry/spec/blob/main/message/spec.md" data-href="https://github.com/xregistry/spec/blob/main/message/spec.md"&gt;message definitions&lt;/a&gt;&amp;nbsp;specification defines a sub-registry for event and message definitions. Initially, we only allowed for declaring CloudEvents, but we quickly realized that declaring metadata for all other major messaging protocols (AMQP, MQTT, Kafka, etc.) would be useful as well, even in combination with CloudEvents. The message definition registry allows declaring both protocol-specific metadata and envelope metadata for events, including field-level descriptions and type information. String-typed metadata fields can be declared as being URI templates, which allows declaring placeholders and simple filter wildcards. Each message definition can be linked to a schema from the schema registry or can embed a local schema for the payload.&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="115"&gt;The grouping mechanism of xRegistry requires that message definitions are grouped, which is a very convenient way to organize message definitions that apply to a specific communication channel. A message definition group can therefore form a logical interface for a specific communication channel, e.g. a Kafka topic or an AMQP queue.&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="121"&gt;The&amp;nbsp;&lt;a href="https://github.com/xregistry/spec/blob/main/endpoint/spec.md" data-href="https://github.com/xregistry/spec/blob/main/endpoint/spec.md"&gt;endpoint registry&lt;/a&gt;&amp;nbsp;specification defines a sub-registry for event sources (consumer endpoints) and sinks (publisher endpoints) as well as for "subscriber endpoints" that advertise protocol-specific endpoints to establish a consumer relationship, e.g. the address of a Kafka broker to create a new consumer group. The specification explicitly defines protocol-specific metadata for various protocols to help with interoperability. Each endpoint can reference one or more message definition groups from the message definition registry. Each endpoint also forms it own message definition group, meaning it can embed one or more message definitions that are specific to the endpoint.&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="133"&gt;There are some examples of the document form of xRegistry in the&amp;nbsp;&lt;a href="https://github.com/xregistry/spec/tree/main/cloudevents/samples/scenarios" data-href="https://github.com/xregistry/spec/tree/main/cloudevents/samples/scenarios"&gt;samples section&lt;/a&gt;&amp;nbsp;of the project repository. When you look through those, you will likely find that while the specification documents are very detailed, concrete document examples are quite simple to read. The&amp;nbsp;&lt;a href="https://github.com/xregistry/spec/blob/main/cloudevents/samples/schemas/schemastore_org.xreg.json" data-href="https://github.com/xregistry/spec/blob/main/cloudevents/samples/schemas/schemastore_org.xreg.json"&gt;schemastore.org&lt;/a&gt;&amp;nbsp;example shows an xRegistry overlay for the entire schema collection of that site.&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="142"&gt;There is chatter about xRegistry competing with AsyncAPI. I'd say the efforts have very different goals. The xRegistry message definition registry's "message groups" yield a similar concept to AsyncAPI channels, but xRegistry does not define a model for how message flows and channels relate. xRegistry is a metadata catalog first and foremost; its ability to define contracts for channels is a byproduct of its structure.&lt;/p&gt;
&lt;h3 class="code-line" dir="auto" data-line="142"&gt;How is this useful to me? Right now?&lt;/h3&gt;
&lt;p class="code-line" dir="auto" data-line="142"&gt;Follow the links and study the following three examples of xRegistry documents:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/xregistry/spec/blob/main/cloudevents/samples/scenarios/watchkam-jsons07.xreg.json" target="_blank" rel="noopener"&gt;Camera CloudEvents/JSON Schema&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/xregistry/spec/blob/main/cloudevents/samples/scenarios/windgenerator-kafka-avro.xreg.json" target="_blank" rel="noopener"&gt;Wind Generator Kafka/Avro&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/xregistry/spec/blob/main/cloudevents/samples/scenarios/waterboiler-mqtt5-jsons07.xreg.json" target="_blank" rel="noopener"&gt;Waiter Boiler MQTT5/JSON&amp;nbsp;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What you'll find is that these documents are formal definitions of what flows over a Kafka topic, a set of MQTT topics and a generic CloudEvents channel. If you are using Kafka or MQTT or AMQP or NATS or HTTP WebHooks or CloudEvents today, xRegistry gives you an instantly useful way to formally document what's going on in that Kafka topic and in that AMQP queue. Which headers or which key identify which kind of message and what schema is associated with it.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;In a way, this is like WSDL (there's an old term!) or OpenAPI for asynchronous eventing/messaging channels, but for the most popular protocol messages and envelopes and schemas and encodings all at once.&amp;nbsp; Instantly useful as a documentation tool.&lt;/p&gt;
&lt;p&gt;A &lt;a href="https://github.com/xregistry/server"&gt;complete reference implementation of the xRegistry API&lt;/a&gt; is part of the project, which means that you can also stand up a server already to manage your metadata. Front this server with a proxy or API gateway that handles authorization and you've got a very flexible metadata solution.&lt;/p&gt;
&lt;p&gt;Down the road, and that ought not to shock you knowing that I work at Microsoft, these formal declarations of what flows on a messaging/eventing channel will become very concretely useful, because you'll be able to tell Azure and Fabric about your channels with them and our tooling will be able to help you a lot better with wrangling your fast moving data.&lt;/p&gt;
&lt;h3 class="code-line" dir="auto" data-line="142"&gt;What's Next?&lt;/h3&gt;
&lt;p class="code-line" dir="auto" data-line="149"&gt;Now, and this leads me to the "what's next" part, I do think there's a need for becoming formal about relationships between channels and for defining message flows. I do not think that a request/response and client/server "API" notion is the right starting point and approach for that.&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="154"&gt;We are looking at a future of collaborating agentic applications that are strung together through asynchronous communication channels. An agent is getting a job to handle and enlists a number of other agents to help with that job. The work on that job may take a long time and results may be produced progressively over multiple responses or with intermediate states change reports.&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="160"&gt;The&amp;nbsp;&lt;a href="https://www.iso20022.org/" data-href="https://www.iso20022.org/"&gt;ISO 20022&lt;/a&gt;&amp;nbsp;set of standards for financial services defines a message flow diagram for each described business process and associated set of message definitions. These message flows are not APIs, they are often fairly complex, multi-party document exchanges.&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="165"&gt;The&amp;nbsp;&lt;a href="https://www.itu.int/rec/T-REC-Z.120-201102-I/en" data-href="https://www.itu.int/rec/T-REC-Z.120-201102-I/en"&gt;ITU Z.120 "Message Sequence Chart"&lt;/a&gt;&amp;nbsp;standard is fairly ancient and a long and arduous read, but it is good prior art to look at for a formalism to describe message flows. I believe that "sequence diagrams as a contract" is a missing piece in the puzzle of strongly-typed, interoperable, and formally defined asynchronous communication.&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="172"&gt;xRegistry's endpoint definitions with associated message definition groups and schemas are well suited to declare the "instance contracts" in the message sequence chart shown below, but we need an extra formal layer to describe the message flow itself.&lt;/p&gt;
&lt;p class="code-line code-active-line" dir="auto" data-line="177"&gt;&lt;img src="https://vasters.com/clemens/content/binary/msc.png" border="0"&gt;&lt;br&gt;From&amp;nbsp;&lt;a href="https://www.itu.int/rec/T-REC-Z.120-201102-I/en" data-href="https://www.itu.int/rec/T-REC-Z.120-201102-I/en"&gt;ITU Z.120&lt;/a&gt;&lt;/p&gt;
&lt;p class="code-line" dir="auto" data-line="179"&gt;Whatever that contract document will look like, it's metadata and therefore will be managable inside of xRegistry.&lt;/p&gt;&lt;/div&gt;</description><category>cloudevents</category><category>cncf</category><category>xregistry</category></item><item xml:lang="en-us"><trackback:ping>https://vasters.com/clemens/feed/trackback/f8919d23-59e1-4f64-817b-8fb0c46a00af</trackback:ping><pingback:server>https://vasters.com/clemens/feed/pingback</pingback:server><pingback:target>https://vasters.com/clemens/post/f8919d23-59e1-4f64-817b-8fb0c46a00af</pingback:target><dc:creator /><title>A thought experiment: "New JSON Schema"</title><guid isPermaLink="false">https://vasters.com/clemens/post/f8919d23-59e1-4f64-817b-8fb0c46a00af</guid><link>https://vasters.com/clemens/2025/02/19/a-thought-experiment-new-json-schema</link><pubDate>Wed, 19 Feb 2025 11:59:10 GMT</pubDate><description>&lt;div&gt;&lt;p dir="auto"&gt;JSON Schema has been in development since ca. 2009 and has gone through several iterations. Yet, there is still no IETF RFC anyone could really lean on as a standard. Practitioners are largely using "Draft 7" of JSON Schema and the subsequent releases have seen comparatively little adoption.&lt;/p&gt;
&lt;p dir="auto"&gt;The quality of the specs in terms of clarity and precision has been a major issue and the JSON Schema project has stood up a website that explains the spec in more detail than the spec itself.&lt;/p&gt;
&lt;p dir="auto"&gt;Structured metadata is becoming rapidly more important in the world of APIs and LLMs. Large language models can operate better in structured data if they are fed with rich context information and schema documents can provide such context.&lt;/p&gt;
&lt;p dir="auto"&gt;JSON Schema should play a big role in this context, but its complexity and ambiguity and the lack of a finalized standard are major obstacles. Efforts like OpenAPI lean on subsets of JSON Schema and had to invent their own extensions to cover gaps. There are no two implementations of JSON Schema code generators that agree on the output mapping of conditional JSON Schema structures to code, including those for OpenAPI.&lt;/p&gt;
&lt;p dir="auto"&gt;Worse yet, all of these tools (need to) give up on complex JSON Schema constructs at some point and that point is different for each implementation. It's close to impossible to write JSON Schemas that can be used reliably for code generation in a cross-platform and cross-language way unless you scope out a substantial portion of the JSON Schema language.&lt;/p&gt;
&lt;p dir="auto"&gt;There are two major use-case scenarios for JSON Schema and schema languages in general:&lt;/p&gt;
&lt;ol dir="auto"&gt;
&lt;li&gt;Users want to validate JSON data against a schema to ensure that the data conforms to a specific structure and set of constraints.&lt;/li&gt;
&lt;li&gt;Users want to declare data types and structures in a machine-readable format that can be used to generate code, documentation, or other artifacts in a cross-platform, cross-language way.&lt;/li&gt;
&lt;/ol&gt;
&lt;p dir="auto"&gt;JSON Schema has enormously powerful facilities for the first use-case right in its core. All that power comes at the expense of the second use-case.&lt;/p&gt;
&lt;p dir="auto"&gt;The existing drafts of JSON Schema define a pattern-matching language for schema processors that is applied to JSON data as it is being validated. It is not a data definition language. It is a validation language that embeds elements that only look like data definition capabilities. An&amp;nbsp;&lt;code&gt;object&lt;/code&gt;&amp;nbsp;declaration in JSON Schema is a matching expression for a JSON object that contains the properties defined in the schema; it does not define an object type.&lt;/p&gt;
&lt;p dir="auto"&gt;Conditional composition constructs like&amp;nbsp;&lt;code&gt;allOf&lt;/code&gt;,&amp;nbsp;&lt;code&gt;anyOf&lt;/code&gt;,&amp;nbsp;&lt;code&gt;oneOf&lt;/code&gt;,&amp;nbsp;&lt;code&gt;not&lt;/code&gt;, and&amp;nbsp;&lt;code&gt;if&lt;/code&gt;/&lt;code&gt;then&lt;/code&gt;/&lt;code&gt;else&lt;/code&gt;&amp;nbsp;are defined in the core schema language. As powerful as they are, conditional composition of data types is generally not a thing in databases or programming languages, which means that any use of these constructs makes mapping from and to code and databases hard and in many cases impossible while preserving the schema semantics.&lt;/p&gt;
&lt;p dir="auto"&gt;JSON Schema allows for&amp;nbsp;&lt;code&gt;$ref&lt;/code&gt;&amp;nbsp;to reference arbitrary JSON nodes (any of which are schemas) from the same or external document, which adds to the complexity. A single JSON Schema might have dozens of external links to content, strewn across the document, making it very difficult to understand as well as hard and potentially unsafe to process.&lt;/p&gt;
&lt;p dir="auto"&gt;There are also confusing conflicts and overlaps. For instance, JSON Schema has a concept of a type union that can only be used for primitive types. Users frequently side-step that limitation through a&amp;nbsp;&lt;code&gt;oneOf&lt;/code&gt; construct that behaves equivalent to a type union for validation and thus there are factually two type union constructs.&lt;/p&gt;
&lt;p dir="auto"&gt;Enumerations are first-class constructs in many programming languages and generally map symbols to values of a single type. In JSON Schema, enumerations are constraints applied to schemas that are not constrained to the declared type of the same schema and values can be of mixed types.&lt;/p&gt;
&lt;p dir="auto"&gt;There are further issues with the JSON Schema spec like the confusing existence of embedded subschemas or why "vocabularies" for meta-schemas are special-cased and aren't just another schema. This document is not meant to be an exhaustive list of problems.&lt;/p&gt;
&lt;p dir="auto"&gt;JSON Schema, as it stands, is a powerful JSON validation language, but a very poor data definition language.&lt;/p&gt;
&lt;p dir="auto"&gt;For APIs, databases, LLMs, and code generation, the industry needs a great data definition language that can also be used for validation. The priorities for the vast majority of practical future applications of JSON Schema are upside down from the current state of the spec.&lt;/p&gt;
&lt;p dir="auto"&gt;&lt;a href="https://github.com/clemensv/json-cs/tree/main/jsc" target="_blank" rel="noopener"&gt;This set of documents&lt;/a&gt;, a proposal for a &lt;em&gt;"new JSON Schema",&lt;/em&gt; completely refactors JSON Schema into:&lt;/p&gt;
&lt;ol dir="auto"&gt;
&lt;li&gt;&lt;a href="https://github.com/clemensv/json-cs/blob/main/jsc/json-schema-core.md" target="_blank" rel="noopener"&gt;a core data definition language&lt;/a&gt; that maps from and to code and databases in a straightforward way and also takes typical type reuse and extensibility patterns into account.&lt;/li&gt;
&lt;li&gt;a set of optional extensions that provide the powerful composition and validation capabilities that JSON Schema is known for.&lt;/li&gt;
&lt;/ol&gt;
&lt;p dir="auto"&gt;In addition, new JSON Schema has a vastly expanded built-in type system that is not limited to the JSON primitives and includes many extended types that are relevant for modern data processing. The type system also directly addresses common pitfalls of the JSON primitives, such as the limited range and precision of numbers.&lt;/p&gt;
&lt;p dir="auto"&gt;Optional extensions directly support multi-language documentation and alternate names and descriptions for properties and types as well as annotations for scientific units and currencies based on international standards.&lt;br&gt;&lt;br&gt;&lt;a href="https://github.com/clemensv/json-cs/blob/main/jsc/json-schema-primer.md" target="_blank" rel="noopener"&gt;Start with the "primer" document&lt;/a&gt; from which this post is an excerpt.&lt;/p&gt;
&lt;p&gt;&lt;img style="width: 100%;" src="https://vasters.com/clemens/content/binary/newJSONschema.jpeg" border="0"&gt;&lt;/p&gt;&lt;/div&gt;</description><category>xregistry</category></item><item><trackback:ping>https://vasters.com/clemens/feed/trackback/dedcae9b-e806-4b21-be5b-1f1efae99c2b</trackback:ping><pingback:server>https://vasters.com/clemens/feed/pingback</pingback:server><pingback:target>https://vasters.com/clemens/post/dedcae9b-e806-4b21-be5b-1f1efae99c2b</pingback:target><dc:creator /><title>H1/2025 Conference session proposals </title><guid isPermaLink="false">https://vasters.com/clemens/post/dedcae9b-e806-4b21-be5b-1f1efae99c2b</guid><link>https://vasters.com/clemens/2024/11/29/h12025-conference-session-proposals</link><pubDate>Fri, 29 Nov 2024 09:03:50 GMT</pubDate><description>&lt;div&gt;&lt;p&gt;I just put a few new session titles/abstracts into my Sessionize speaker profile for the coming year:&lt;/p&gt;
&lt;p&gt;1. Bringing Clarity to Event Streams: Enabling Analytics and AI Through Rich Metadata https://sessionize.com/s/clemens-vasters/bringing-clarity-to-event-streams-enabling-analyti/111971&lt;/p&gt;
&lt;p&gt;2. Streamifying Reference Data for Temporal Consistency with Telemetry Events https://sessionize.com/s/clemens-vasters/streamifying-reference-data-for-temporal-consisten/111973&lt;/p&gt;
&lt;p&gt;3. Real-time data journeys. Kafka, MQTT, AMQP, HTTP, Web Sockets; protocols, my, oh, my! https://sessionize.com/s/clemens-vasters/real-time-data-journeys.-kafka-mqtt-amqp-http-web-/111974&lt;/p&gt;
&lt;p&gt;4. From Observations to Actions: Real-Time Intelligence with Microsoft Fabric https://sessionize.com/s/clemens-vasters/from-observations-to-actions-real-time-intelligenc/111982&lt;/p&gt;
&lt;p&gt;5. Generating code and projects in all sorts of languages with Python and Jinja2 https://sessionize.com/s/clemens-vasters/generating-code-and-projects-in-all-sorts-of-langu/111972&lt;/p&gt;
&lt;p&gt;(It's an unusual topic for me, but I have a ton of material for&amp;nbsp;&lt;strong class="ql-hashtag" data-test-ql-hashtag="true"&gt;#5&lt;/strong&gt;; that'll have to be a 2nd talk at a conference along one of the others, though)&lt;/p&gt;
&lt;p&gt;If you run a conference and find any of these abstracts interesting, let me know: clemensv@microsoft.com&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/div&gt;</description><category>5</category></item><item xml:lang="en-us"><trackback:ping>https://vasters.com/clemens/feed/trackback/a7818f6c-464e-414a-95eb-b50cea6bd0b0</trackback:ping><pingback:server>https://vasters.com/clemens/feed/pingback</pingback:server><pingback:target>https://vasters.com/clemens/post/a7818f6c-464e-414a-95eb-b50cea6bd0b0</pingback:target><dc:creator /><title>"Plain JSON" encoding for Apache Avro</title><guid isPermaLink="false">https://vasters.com/clemens/post/a7818f6c-464e-414a-95eb-b50cea6bd0b0</guid><link>https://vasters.com/clemens/2024/11/13/plain-json-encoding-for-apache-avro</link><pubDate>Wed, 13 Nov 2024 12:13:07 GMT</pubDate><description>&lt;div&gt;&lt;article class="markdown-body entry-content container-lg"&gt;Also available &lt;a href="https://github.com/clemensv/avrotize/blob/master/avrojson.md"&gt;here&lt;/a&gt;. &lt;a href="https://issues.apache.org/jira/browse/AVRO-3986"&gt;JIRA-3986&lt;/a&gt;. Illustrating &lt;a href="https://github.com/apache/avro/pull/2888"&gt;Avro project PR for C#&lt;/a&gt;.&lt;/article&gt;
&lt;article class="markdown-body entry-content container-lg"&gt;&lt;hr&gt;
&lt;p dir="auto"&gt;The Apache Avro project defines a JSON Encoding, which is optimized for encoding data in JSON, but primarily aimed at exchanging data between implementations of the Apache Avro specification. The choices made for this encoding severely limit the interoperability with other JSON serialization frameworks. This document defines an alternate, additional mode for Avro JSON Encoders, preliminarily named "Plain JSON", that specifically addresses identified interoperability blockers.&lt;/p&gt;
&lt;p dir="auto"&gt;While this document is a proposal for a set of new features in Apache Avro, the extensibility of Avro's schema model allows for the implementation of these features separately from the Avro project. Out of the available and popular schema languages for data exchange, Avro schema provides the cleanest foundation for mapping wire representations to programming language types and database tables, which is why interoperability of Avro with the most popular text encoding format for structured data, JSON, is very desirable.&lt;/p&gt;
&lt;p dir="auto"&gt;With Avro's strength and focus being its binary encoding, supporting JSON is specifically desireable in interoperability scenarios where either the producer or the consumer of the encoded data is using a different JSON encoding framework, or where JSON is crafted or evaluated directly by the application.&lt;/p&gt;
&lt;p dir="auto"&gt;As most JSON document instances can be structurally described by Avro Schema, the interoperability case is for JSON data, described by Avro Schema, to be accepted by an Apache Avro messaging application, and for that data then to be forwarded onwards using Avro binary encoding. Reversely, it needs to be possible for an application to transform an Avro binary encoded data structure into JSON data that is understood by parties that expect to handle JSON. The kinds applications requiring such transformation capabilities are stream processing frameworks, API gateways and (reverse) proxies, and integration brokers.&lt;/p&gt;
&lt;p dir="auto"&gt;The intent of this proposal is for the Avro "JsonEncoder" implementations to have a new mode parameter, accepting an enumeration choice out of the options "Avro Json" (AVRO_JSON, AvroJson, etc), which is Avro's default JSON encoding, and "Plain JSON" (PLAIN_JSON, PlainJson, etc). The rules for the "Plain JSON" mode are described herein.&lt;/p&gt;
&lt;p dir="auto"&gt;The "Plain JSON" mode is a selector for enabling set of features that are described below. Implementations MAY also choose for these features to be individually selectable for the "Avro JSON" mode, for instance letting the user use the "Avro JSON" mode primarily, but opting into the binary data handling or date-time handling features described here. However, the "Plain JSON" mode that combines these features MUST be implemented to ensure interoperability.&lt;/p&gt;
&lt;div class="markdown-heading" dir="auto"&gt;
&lt;h2 class="heading-element" dir="auto" tabindex="-1"&gt;Notational Conventions&lt;/h2&gt;
&lt;a id="user-content-notational-conventions" class="anchor" href="#notational-conventions" aria-label="Permalink: Notational Conventions"&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p dir="auto"&gt;The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.&lt;/p&gt;
&lt;div class="markdown-heading" dir="auto"&gt;
&lt;h2 class="heading-element" dir="auto" tabindex="-1"&gt;Interoperability issues of the Avro JSON Encoding with common JSON usage&lt;/h2&gt;
&lt;a id="user-content-interoperability-issues-of-the-avro-json-encoding-with-common-json-usage" class="anchor" href="#interoperability-issues-of-the-avro-json-encoding-with-common-json-usage" aria-label="Permalink: Interoperability issues of the Avro JSON Encoding with common JSON usage"&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p dir="auto"&gt;There are several distinct issues in the Avro JSON Encoding that cause conflicts with common usage of JSON and many serialization frameworks. It needs to be emphasized that none of these issues are conformance issues with the JSON specification (RFC8259), but rather stem from the JSON specification's inherent limitations. JSON does not define binary data, date or time types. JSON also has no concept of a type-hint for data structures (i.e. objects), which would allow serialization frameworks to establish an unambiguous mapping between a data type in a programming language or schema and the encoded type in JSON.&lt;/p&gt;
&lt;p dir="auto"&gt;There are, however, commonly used conventions to address these shortcomings of the core JSON specification:&lt;/p&gt;
&lt;ul dir="auto"&gt;
&lt;li&gt;Binary data: Binary data is commonly encoded using the base64 encoding and stored in string-typed values.&lt;/li&gt;
&lt;li&gt;Date and time data: Date and time data is commonly encoded using the RFC3339 profile of ISO8601 and stored in string-typed values.&lt;/li&gt;
&lt;li&gt;Type hints: In its native type system, JSON value types are distinguished by notation where 'null' values, strings, numbers, booleans, arrays, and objects are identifiable through the syntax. While JSON has no further data type concepts, several serialization frameworks and even some standards leaning on JSON (e.g. OpenAPI) introduce the notion of a "discriminator" property, which is inside the encoded object and unambiguously identifies the type such that the decoding stage can instantiate and populate the correct type in cases where multiple candidate types exist.&lt;/li&gt;
&lt;/ul&gt;
&lt;p dir="auto"&gt;On each of these items, the Avro JSON encoding's choices are in direct conflict with predominant practice:&lt;/p&gt;
&lt;ul dir="auto"&gt;
&lt;li&gt;Binary data: Binary data is encoded in strings using Unicode escape sequences (example: "\u00DE\u00AD\u00BE\u00EF"), which leads to a 500% overhead compared to the encoded bytes vs. a 33% overhead when using Base64.&lt;/li&gt;
&lt;li&gt;Date and time data: Avro handles date and time as logical types, extending either long or int, using the UNIX epoch as the baseline. Durations are expressed using a bespoke data structure. As there are no handling rules for logical types in the JSON encoding, the encoded results are therefore epoch numbers without annotations like time zone offsets.&lt;/li&gt;
&lt;li&gt;Type-hints: Whenever types can be ambiguous in Avro, which is the case with type unions, the Avro JSON encoding prescribes encoding the value wrapped inside an object with a single property where the property's name is the type name, e.g. &lt;code&gt;"myprop": {"string": "value"}&lt;/code&gt;. 'null' values are encoded as 'null', e.g. &lt;code&gt;"myprop": null&lt;/code&gt;. For primitive types, this is in conflict with JSON's native type model that already makes the distinction syntactically. For object types (Avro records), the wrapper is in conflict with standing practice where the discriminator is inlined.&lt;/li&gt;
&lt;/ul&gt;
&lt;p dir="auto"&gt;In addition, there are three general limitations of Avro's type and schema model that result in potential interoperability blockers:&lt;/p&gt;
&lt;ul dir="auto"&gt;
&lt;li&gt;Avro represents decimal numeric types as a logical type annotating &lt;code&gt;fixed&lt;/code&gt; or &lt;code&gt;byte&lt;/code&gt;, which results in an encoded byte sequence in the JSON encoding that cannot be interpreted without the Avro schema and is therefore undecipherable for regular JSON consumers.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;name&lt;/code&gt; fields in Avro are limited to a character set that can be easily mapped to mostly any programming language and database, but JSON object keys are not.&lt;/li&gt;
&lt;li&gt;JSON documents may have top-level arrays and maps, while Avro schemas only allow &lt;code&gt;record&lt;/code&gt; and &lt;code&gt;enum&lt;/code&gt; as independent types and therefore at the top-level of a schema.&lt;/li&gt;
&lt;/ul&gt;
&lt;p dir="auto"&gt;As a consequence of this, the current implementations of the Avro JSON Encoding do not interoperate well with "plain JSON" as input and often do not yield useful plain JSON as output. There is a "happy path" on which the Avro JSON Encoding does line up with common usage, but it's easy to stray off from it.&lt;/p&gt;
&lt;div class="markdown-heading" dir="auto"&gt;
&lt;h2 class="heading-element" dir="auto" tabindex="-1"&gt;The Plain JSON encoding&lt;/h2&gt;
&lt;a id="user-content-the-plain-json-encoding" class="anchor" href="#the-plain-json-encoding" aria-label="Permalink: The Plain JSON encoding"&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p dir="auto"&gt;The Plain JSON encoding mode of Apache Avro consists of a combination of 7 distinct features that are defined in this section. The design is grounded in the relevant IETF RFCs and provides the broadest interoperability with common usage of JSON, while yet preserving type integrity and precision in all cases where the Avro Schema is known to the decoding party.&lt;/p&gt;
&lt;p dir="auto"&gt;The features are designed to be orthogonal and can be implemented separately.&lt;/p&gt;
&lt;ul dir="auto"&gt;
&lt;li&gt;&lt;a href="#feature-1-alternate-names"&gt;1: Alternate names&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#feature-2-avro-binary-and-fixed-type-data-encoding"&gt;2: Avro &lt;code&gt;binary&lt;/code&gt; and &lt;code&gt;fixed&lt;/code&gt; type data encoding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#feature-3-avro-decimal-logical-type-data-encoding"&gt;3: Avro &lt;code&gt;decimal&lt;/code&gt; logical type data encoding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#feature-4-avro-time-date-and-duration-logical-types"&gt;4: Avro time, date, and duration logical types&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#feature-5-handling-unions-with-primitive-type-values-and-enum-values"&gt;5: Handling unions with primitive type values and enum values&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#feature-6-handling-unions-of-record-values-and-of-maps"&gt;6: Handling unions of record values and of maps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#feature-7-document-root-records"&gt;7: Document root records&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p dir="auto"&gt;Features 2, 3, 4, and 5 are trivial on all platforms and frameworks that handle JSON. Features 1 and 7 are hints for the JSON encoder and decoder to be able to handle JSON data that is not conforming to Avro's naming and structure constraints. Feature 6 provides a mechanism to handle unions of record types that is aligned with common JSON encodation frameworks and JSON Schema's "oneOf" type composition.&lt;/p&gt;
&lt;div class="markdown-heading" dir="auto"&gt;
&lt;h3 class="heading-element" dir="auto" tabindex="-1"&gt;Feature 1: Alternate names&lt;/h3&gt;
&lt;a id="user-content-feature-1-alternate-names" class="anchor" href="#feature-1-alternate-names" aria-label="Permalink: Feature 1: Alternate names"&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p dir="auto"&gt;JSON objects allow for keys with arbitrary unicode strings, with the only restriction being uniqueness of keys within an object. Uniqueness is a "SHOULD" rule in &lt;a href="https://www.rfc-editor.org/rfc/rfc8259#section-4" rel="nofollow"&gt;RFC8259, Section 4&lt;/a&gt;, which is interpreted as REQUIRED for this specification since it is common practice.&lt;/p&gt;
&lt;p dir="auto"&gt;The character set permitted for Avro names is constrained by the regular expression &lt;code&gt;[A-Za-z_][A-Za-z0-9_]*&lt;/code&gt;, which poses an interoperability problem with JSON, especially in scenarios where internationalization is a concern. While English is the dominant language in most developer scenarios, metadata might be defined by end-users and in their own language. It's also fairly common for JSON object keys to contain word-separator characters other than '_' and keys may quite well start with a number.&lt;/p&gt;
&lt;p dir="auto"&gt;As the Avro project will presumably want to avoid introducing schema attributes that are JSON-specific and will want to use new schema constructs for additional needs as they arise, the alternate names feature introduces a map of alternate names of which the plain JSON feature reserves a key:&lt;/p&gt;
&lt;div class="markdown-heading" dir="auto"&gt;
&lt;h4 class="heading-element" dir="auto" tabindex="-1"&gt;&lt;code&gt;altnames&lt;/code&gt; map&lt;/h4&gt;
&lt;a id="user-content-altnames-map" class="anchor" href="#altnames-map" aria-label="Permalink: altnames map"&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p dir="auto"&gt;Wherever Avro Schema requires a &lt;code&gt;name&lt;/code&gt; field, an &lt;code&gt;altnames&lt;/code&gt; map MAY be defined alongside the &lt;code&gt;name&lt;/code&gt; field, which provides a map of alternate names. Those names may be local-language identifiers, display names, or names that contain characters disallowed in Avro. The map key identifies the context in which the alternate name is used.&lt;/p&gt;
&lt;p dir="auto"&gt;This specification reserves the &lt;code&gt;json&lt;/code&gt; key in the &lt;code&gt;altnames&lt;/code&gt; map.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p dir="auto"&gt;A display-name feature might reserve &lt;code&gt;display:{IANA-subtag}&lt;/code&gt; as keys. This assumed convention is used in the following example just for illustration of the &lt;code&gt;altnames&lt;/code&gt; feature.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p dir="auto"&gt;Assume the following JSON input document with German-language keys that represents a row in commercial order document:&lt;/p&gt;
&lt;div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto"&gt;
&lt;pre&gt;{
  &lt;span class="pl-ent"&gt;"Artikelschl&amp;uuml;ssel"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;1234&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="pl-ent"&gt;"St&amp;uuml;ckzahl"&lt;/span&gt;: &lt;span class="pl-c1"&gt;42&lt;/span&gt;,
  &lt;span class="pl-ent"&gt;"Gr&amp;ouml;&amp;szlig;e"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Extragro&amp;szlig;&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
}&lt;/pre&gt;
&lt;div class="zeroclipboard-container"&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p dir="auto"&gt;Without the alternate names feature, the Avro schema would not be able to match the keys in the JSON document since &lt;code&gt;&amp;uuml;&lt;/code&gt; and &lt;code&gt;&amp;szlig;&lt;/code&gt; are not allowed. With the alternate names feature, the schema can be defined as follows:&lt;/p&gt;
&lt;div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto"&gt;
&lt;pre&gt;{
  &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;record&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="pl-ent"&gt;"namespace"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;com.example&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Article&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="pl-ent"&gt;"fields"&lt;/span&gt;: [
    {
      &lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;articleKey&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
      &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;string&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
      &lt;span class="pl-ent"&gt;"altnames"&lt;/span&gt;: {
        &lt;span class="pl-ent"&gt;"json"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Artikelschl&amp;uuml;ssel&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
        &lt;span class="pl-ent"&gt;"display:de"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Artikelschl&amp;uuml;ssel&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
        &lt;span class="pl-ent"&gt;"display:en"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Article Key&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
      }
    },
    {
      &lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;quantity&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
      &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;int&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
      &lt;span class="pl-ent"&gt;"altnames"&lt;/span&gt;: {
        &lt;span class="pl-ent"&gt;"json"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;St&amp;uuml;ckzahl&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
        &lt;span class="pl-ent"&gt;"display:de"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;St&amp;uuml;ckzahl&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
        &lt;span class="pl-ent"&gt;"display:en"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Quantity&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
      }
    },
    {
      &lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;size&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
      &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;sizeEnum&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
      &lt;span class="pl-ent"&gt;"altnames"&lt;/span&gt;: {
        &lt;span class="pl-ent"&gt;"json"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Gr&amp;ouml;&amp;szlig;e&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
        &lt;span class="pl-ent"&gt;"display:de"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Gr&amp;ouml;&amp;szlig;e&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
        &lt;span class="pl-ent"&gt;"display:en"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Size&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
      }
    }
  ]
}&lt;/pre&gt;
&lt;div class="zeroclipboard-container"&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p dir="auto"&gt;When the JSON decoder (de-)encodes a named item, the encoder MUST use the value from the &lt;code&gt;altnames&lt;/code&gt; entry with the &lt;code&gt;json&lt;/code&gt; key as the name for the corresponding JSON element, when present.&lt;/p&gt;
&lt;div class="markdown-heading" dir="auto"&gt;
&lt;h4 class="heading-element" dir="auto" tabindex="-1"&gt;&lt;code&gt;altsymbols&lt;/code&gt; map&lt;/h4&gt;
&lt;a id="user-content-altsymbols-map" class="anchor" href="#altsymbols-map" aria-label="Permalink: altsymbols map"&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p dir="auto"&gt;The &lt;code&gt;altsymbols&lt;/code&gt; map is a similar feature to &lt;code&gt;altnames&lt;/code&gt;, but it is used for alternate names of enum symbols. The &lt;code&gt;altsymbols&lt;/code&gt; map provides alternate names for symbols. As with &lt;code&gt;altnames&lt;/code&gt;, the &lt;code&gt;altsymbols&lt;/code&gt; map key identifies the context in which the alternate name is used. The values of the &lt;code&gt;altsymbols&lt;/code&gt; map are maps where the keys are symbols as defined in the &lt;code&gt;symbols&lt;/code&gt; field and the values are the corresponding alternate names.&lt;/p&gt;
&lt;p dir="auto"&gt;Any symbol key present in the &lt;code&gt;altsymbols&lt;/code&gt; map MUST exist in the &lt;code&gt;symbols&lt;/code&gt; field. Symbols in the &lt;code&gt;symbols&lt;/code&gt; field MAY be omitted from the &lt;code&gt;altsymbols&lt;/code&gt; map.&lt;/p&gt;
&lt;div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto"&gt;
&lt;pre&gt;{
  &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;enum&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;sizeEnum&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="pl-ent"&gt;"symbols"&lt;/span&gt;: [&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;S&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;M&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;L&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;XL&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;],
  &lt;span class="pl-ent"&gt;"altsymbols"&lt;/span&gt;: {
    &lt;span class="pl-ent"&gt;"json"&lt;/span&gt;: {
      &lt;span class="pl-ent"&gt;"S"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Klein&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
      &lt;span class="pl-ent"&gt;"M"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Mittel&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
      &lt;span class="pl-ent"&gt;"L"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Gro&amp;szlig;&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
      &lt;span class="pl-ent"&gt;"XL"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Extragro&amp;szlig;&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
    },
    &lt;span class="pl-ent"&gt;"display:en"&lt;/span&gt;: {
      &lt;span class="pl-ent"&gt;"S"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Small&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
      &lt;span class="pl-ent"&gt;"M"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Medium&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
      &lt;span class="pl-ent"&gt;"L"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Large&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
      &lt;span class="pl-ent"&gt;"XL"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Extra Large&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
    }
  }
}&lt;/pre&gt;
&lt;div class="zeroclipboard-container"&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p dir="auto"&gt;When the JSON decoder (de-)encodes an enum symbol, the encoder MUST use the value from the &lt;code&gt;altsymbols&lt;/code&gt; entry with the &lt;code&gt;json&lt;/code&gt; key as the string representing the enum value, when present.&lt;/p&gt;
&lt;div class="markdown-heading" dir="auto"&gt;
&lt;h3 class="heading-element" dir="auto" tabindex="-1"&gt;Feature 2: Avro &lt;code&gt;binary&lt;/code&gt; and &lt;code&gt;fixed&lt;/code&gt; type data encoding&lt;/h3&gt;
&lt;a id="user-content-feature-2-avro-binary-and-fixed-type-data-encoding" class="anchor" href="#feature-2-avro-binary-and-fixed-type-data-encoding" aria-label="Permalink: Feature 2: Avro binary and fixed type data encoding"&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p dir="auto"&gt;When encoding data typed with the Avro &lt;code&gt;binary&lt;/code&gt; or &lt;code&gt;fixed&lt;/code&gt; types, the byte sequence is encoded into and from Base64 encoded string values, conforming with IETF RFC4648, Section 4.&lt;/p&gt;
&lt;div class="markdown-heading" dir="auto"&gt;
&lt;h3 class="heading-element" dir="auto" tabindex="-1"&gt;Feature 3: Avro &lt;code&gt;decimal&lt;/code&gt; logical type data encoding&lt;/h3&gt;
&lt;a id="user-content-feature-3-avro-decimal-logical-type-data-encoding" class="anchor" href="#feature-3-avro-decimal-logical-type-data-encoding" aria-label="Permalink: Feature 3: Avro decimal logical type data encoding"&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p dir="auto"&gt;When encoding data typed with the Avro logical &lt;code&gt;decimal&lt;/code&gt; type, the numeric value is encoded into a from a JSON &lt;code&gt;number&lt;/code&gt; value. JSON numbers are represented as text and do not lose precision as IEEE754 floating points do.&lt;/p&gt;
&lt;p dir="auto"&gt;When using a JSON library to implement the encoding, decimal values MUST NOT be converted through an IEEE floating point type (e.g. double or float in most programming languages) but must use the native decimal data type.&lt;/p&gt;
&lt;div class="markdown-heading" dir="auto"&gt;
&lt;h3 class="heading-element" dir="auto" tabindex="-1"&gt;Feature 4: Avro time, date, and duration logical types&lt;/h3&gt;
&lt;a id="user-content-feature-4-avro-time-date-and-duration-logical-types" class="anchor" href="#feature-4-avro-time-date-and-duration-logical-types" aria-label="Permalink: Feature 4: Avro time, date, and duration logical types"&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p dir="auto"&gt;When encoding data typed with one of Avro's logical data types for dates and times, the data is encoded into and from a JSON &lt;code&gt;string&lt;/code&gt; value, which is an expression as defined in IETF RFC3339.&lt;/p&gt;
&lt;p dir="auto"&gt;Specifically, the logical types are mapped to certain grammar elements defined in RFC3339 as defined in the following table:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;logicalType&lt;/th&gt;
&lt;th&gt;RFC3339 grammar element&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;date&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;RFC3339 5.6. &amp;ldquo;full-date&amp;rdquo;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;time-millis&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;RFC3339 5.6. &amp;ldquo;date-time&amp;rdquo;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;time-micros&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;RFC3339 5.6. &amp;ldquo;partial-time&amp;rdquo;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;timestamp-millis&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;RFC3339 5.6 &amp;ldquo;date-time&amp;rdquo;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;timestamp-micros&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;RFC3339 5.6 &amp;ldquo;date-time&amp;rdquo;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;local-timestamp-millis&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;RFC3339 5.6 &amp;ldquo;date-time&amp;rdquo;, ignoring offset (note RFC 3339 4.4)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;local-timestamp-micros&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;RFC3339 5.6 &amp;ldquo;date-time&amp;rdquo; , ignoring offset (note RFC 3339 4.4)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;duration&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;RFC3339 Appendix A &amp;ldquo;duration&amp;rdquo;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="markdown-heading" dir="auto"&gt;
&lt;h3 class="heading-element" dir="auto" tabindex="-1"&gt;Feature 5: Handling unions with primitive type values and enum values&lt;/h3&gt;
&lt;a id="user-content-feature-5-handling-unions-with-primitive-type-values-and-enum-values" class="anchor" href="#feature-5-handling-unions-with-primitive-type-values-and-enum-values" aria-label="Permalink: Feature 5: Handling unions with primitive type values and enum values"&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p dir="auto"&gt;Unions of primitive types and of enum values are handled through JSON values' (RFC8259, Section 3) ability to reflect variable types.&lt;/p&gt;
&lt;p dir="auto"&gt;Given a type union of &lt;code&gt;[string, null]&lt;/code&gt; and a string value "test", a encoded field named "example" is encoded as &lt;code&gt;"example": null&lt;/code&gt; or &lt;code&gt;"example": "test"&lt;/code&gt;. For null-valued fields, the JSON encoder MAY omit the field entirely. During decoding, missing fields are set to null. If a default value is defined for the field, decoding MUST set the field value to the default value.&lt;/p&gt;
&lt;p dir="auto"&gt;For a type union of &lt;code&gt;[string,int]&lt;/code&gt; and string values "2" and the int value 2, a encoded field named "example" is encoded as &lt;code&gt;"example": "2"&lt;/code&gt; or &lt;code&gt;"example":2&lt;/code&gt;.&lt;/p&gt;
&lt;p dir="auto"&gt;For a type union of &lt;code&gt;[null, myEnum]&lt;/code&gt; with myEnum being an enum type having symbols "test1" and "test2", a encoded field named "example" is encoded as &lt;code&gt;"example": null&lt;/code&gt; or &lt;code&gt;"example": "test1"&lt;/code&gt; or &lt;code&gt;"example": "test2"&lt;/code&gt;.&lt;/p&gt;
&lt;p dir="auto"&gt;Instances of unions of primitive types with arrays and records or maps can also be distinguished through the JSON grammar and type model. Unions of multiple records are discussed in Feature 6 below.&lt;/p&gt;
&lt;p dir="auto"&gt;For completeness, these are the updated type mappings of Avro types to JSON types for the plain JSON encoding.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Avro type&lt;/th&gt;
&lt;th&gt;JSON type&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;null&lt;/td&gt;
&lt;td&gt;null&lt;/td&gt;
&lt;td&gt;The field MAY be omitted&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;int,long&lt;/td&gt;
&lt;td&gt;integer&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;float,double&lt;/td&gt;
&lt;td&gt;number&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bytes&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Base64 string, see &lt;a href="#feature-2-avro-binary-and-fixed-type-data-encoding"&gt;Feature 2&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;record&lt;/td&gt;
&lt;td&gt;object&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;enum&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;array&lt;/td&gt;
&lt;td&gt;array&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;map&lt;/td&gt;
&lt;td&gt;object&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fixed&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Base64 string, see &lt;a href="#feature-2-avro-binary-and-fixed-type-data-encoding"&gt;Feature 2&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;date/time&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;See &lt;a href="#feature-4-avro-time-date-and-duration-logical-types"&gt;Feature 4&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UUID&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;decimal&lt;/td&gt;
&lt;td&gt;number&lt;/td&gt;
&lt;td&gt;See &lt;a href="#feature-3-avro-decimal-logical-type-data-encoding"&gt;Feature 3&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="markdown-heading" dir="auto"&gt;
&lt;h3 class="heading-element" dir="auto" tabindex="-1"&gt;Feature 6: Handling unions of record values and of maps&lt;/h3&gt;
&lt;a id="user-content-feature-6-handling-unions-of-record-values-and-of-maps" class="anchor" href="#feature-6-handling-unions-of-record-values-and-of-maps" aria-label="Permalink: Feature 6: Handling unions of record values and of maps"&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p dir="auto"&gt;As discussed in the overview, JSON does not have an inherent concept of a type-hint that allows distinguishing object data types. Indeed, it has no concept of constraining and further specifying the &lt;code&gt;object&lt;/code&gt; type, at all.&lt;/p&gt;
&lt;p dir="auto"&gt;The JSON Schema project has defined a schema language specifically for JSON data and provides a type concept for &lt;code&gt;object&lt;/code&gt;. In JSON interoperability scenarios, JSON Schema, or frameworks that infer their type concepts from JSON Schema, will often play a role on the producer or consumer side due to its popularity.&lt;/p&gt;
&lt;p dir="auto"&gt;JSON Schema is primarily a schema model that serves to validate JSON documents. Its "oneOf" type composition construct is equivalent to Avro's union concept in function. Out of a choice of multiple type options, exactly one option MUST match the JSON element that is being validated, otherwise the validation fails. Any implementation of a JSON Schema validator must therefore be able to test the given JSON element against all available options and then determine the matching type option. Any implementation of a schema driven decoder can use the same strategy to select which type to instantiate and populate.&lt;/p&gt;
&lt;p dir="auto"&gt;JSON Schema does not define a type-hint for this purpose, but makes it the schema designer's task to create type definitions that are structurally distinct such that the "oneOf" test always yields one of the types when given JSON element instances. Schema designers then occasionally resort to introducing their own type-hints by either defining a discriminator property with a single-value &lt;code&gt;enum&lt;/code&gt; or with a &lt;code&gt;const&lt;/code&gt; value, where the discriminator property name is the same across the type options, but the values of the &lt;code&gt;enum&lt;/code&gt; or &lt;code&gt;const&lt;/code&gt; are different. We will lean on this practice in the following.&lt;/p&gt;
&lt;div class="markdown-heading" dir="auto"&gt;
&lt;h4 class="heading-element" dir="auto" tabindex="-1"&gt;Type structure matching&lt;/h4&gt;
&lt;a id="user-content-type-structure-matching" class="anchor" href="#type-structure-matching" aria-label="Permalink: Type structure matching"&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p dir="auto"&gt;Consider the following Avro schema with a type union of two record types:&lt;/p&gt;
&lt;div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto"&gt;
&lt;pre&gt;{
  &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;record&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;ContactList&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="pl-ent"&gt;"fields"&lt;/span&gt;: [
    {
      &lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;contacts&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
      &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;array&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
      &lt;span class="pl-ent"&gt;"items"&lt;/span&gt;: [
        {
          &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;record&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
          &lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;CustomerRecord&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
          &lt;span class="pl-ent"&gt;"fields"&lt;/span&gt;: [
            {&lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;name&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;string&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;},
            {&lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;age&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;int&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;}
            {&lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;customerId&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;string&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;}
          ]
        },
        {
          &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;record&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
          &lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;EmployeeRecord&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
          &lt;span class="pl-ent"&gt;"fields"&lt;/span&gt;: [
            {&lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;name&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;string&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;},
            {&lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;age&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;int&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;},
            {&lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;employeeId&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;string&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;}
          ]
        }
      ]
    }
  ]
}&lt;/pre&gt;
&lt;div class="zeroclipboard-container"&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p dir="auto"&gt;Now consider the following JSON document:&lt;/p&gt;
&lt;div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto"&gt;
&lt;pre&gt;{
  &lt;span class="pl-ent"&gt;"contacts"&lt;/span&gt;: [
    {&lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Alice&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"age"&lt;/span&gt;: &lt;span class="pl-c1"&gt;42&lt;/span&gt;, &lt;span class="pl-ent"&gt;"customerId"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;1234&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;},
    {&lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Bob&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"age"&lt;/span&gt;: &lt;span class="pl-c1"&gt;43&lt;/span&gt;, &lt;span class="pl-ent"&gt;"employeeId"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;5678&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;}
  ]
}&lt;/pre&gt;
&lt;div class="zeroclipboard-container"&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p dir="auto"&gt;We can clearly distinguish the two record types by the presence of the respectively required &lt;code&gt;customerId&lt;/code&gt; or &lt;code&gt;employeeId&lt;/code&gt; field.&lt;/p&gt;
&lt;p dir="auto"&gt;When decoding a type union, the JSON decoder MUST test the JSON element against all available type options. A JSON element matches if it can be correctly and completely decoded given the type-union candidate schema, including all applicable nested or referenced definitions. If more than one of the options matches, decoding MUST fail. The JSON decoder MUST select the type option that matches the JSON element and instantiate and populate the corresponding type.&lt;/p&gt;
&lt;p dir="auto"&gt;For performance reasons, it is highly desirable to avoid having to test a JSON element against all possible type options in a union and instead have a single property that can be tested first and short-circuits the type matching process. We discuss that next.&lt;/p&gt;
&lt;div class="markdown-heading" dir="auto"&gt;
&lt;h4 class="heading-element" dir="auto" tabindex="-1"&gt;Discriminator property&lt;/h4&gt;
&lt;a id="user-content-discriminator-property" class="anchor" href="#discriminator-property" aria-label="Permalink: Discriminator property"&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p dir="auto"&gt;When we assume the Avro schema to be slightly different, we might end up with an ambiguity that is not as easy to resolve. Let the &lt;code&gt;employeeId&lt;/code&gt; and &lt;code&gt;customerId&lt;/code&gt; fields be optional in the schema above, both typed as &lt;code&gt;["string", "null"]&lt;/code&gt;.&lt;/p&gt;
&lt;p dir="auto"&gt;When we now consider the following JSON document, we can't decide on the type and will fail decoding:&lt;/p&gt;
&lt;div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto"&gt;
&lt;pre&gt;{
  &lt;span class="pl-ent"&gt;"contacts"&lt;/span&gt;: [
    {&lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Alice&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"age"&lt;/span&gt;: &lt;span class="pl-c1"&gt;42&lt;/span&gt;},
    {&lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Bob&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"age"&lt;/span&gt;: &lt;span class="pl-c1"&gt;43&lt;/span&gt;}
  ]
}&lt;/pre&gt;
&lt;div class="zeroclipboard-container"&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p dir="auto"&gt;To resolve this ambiguity, we can introduce a discriminator property that clearly identifies the type of the record.&lt;/p&gt;
&lt;p dir="auto"&gt;Instead of introducing a schema attribute that is specific to JSON, we instead introduce a new Avro schema attribute &lt;code&gt;const&lt;/code&gt; that defines a constant value for the field it is defined on.&lt;/p&gt;
&lt;p dir="auto"&gt;The value of the &lt;code&gt;const&lt;/code&gt; field must match the field type. The value of the field MUST always match the &lt;code&gt;const&lt;/code&gt; value. During decoding, decoding MUST fail if the field value is not equal to the &lt;code&gt;const&lt;/code&gt; value. This rule ensures the function of &lt;code&gt;const&lt;/code&gt; as a discriminator. The &lt;code&gt;const&lt;/code&gt; field is only allowed on fields of primitive types and enum types.&lt;/p&gt;
&lt;p dir="auto"&gt;Consider this Avro schema:&lt;/p&gt;
&lt;div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto"&gt;
&lt;pre&gt;{
  &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;record&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;ContactList&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="pl-ent"&gt;"fields"&lt;/span&gt;: [
    {
      &lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;contacts&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
      &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;array&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
      &lt;span class="pl-ent"&gt;"items"&lt;/span&gt;: [
        {
          &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;record&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
          &lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;CustomerRecord&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
          &lt;span class="pl-ent"&gt;"fields"&lt;/span&gt;: [
            {&lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;name&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;string&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;},
            {&lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;age&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;int&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;},
            {&lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;customerId&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: [&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;string&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;null&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;]},
            {&lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;type&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;string&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"const"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;customer&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;}
          ]
        },
        {
          &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;record&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
          &lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;EmployeeRecord&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
          &lt;span class="pl-ent"&gt;"fields"&lt;/span&gt;: [
            {&lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;name&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;string&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;},
            {&lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;age&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;int&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;},
            {&lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;employeeId&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: [&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;string&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;null&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;]},
            {&lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;type&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;string&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"const"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;employee&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;}
          ]
        }
      ]
    }
  ]
}&lt;/pre&gt;
&lt;div class="zeroclipboard-container"&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p dir="auto"&gt;The JSON document MUST now include the discriminator:&lt;/p&gt;
&lt;div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto"&gt;
&lt;pre&gt;{
  &lt;span class="pl-ent"&gt;"contacts"&lt;/span&gt;: [
    {&lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Alice&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"age"&lt;/span&gt;: &lt;span class="pl-c1"&gt;42&lt;/span&gt;, &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;customer&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;},
    {&lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Bob&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"age"&lt;/span&gt;: &lt;span class="pl-c1"&gt;43&lt;/span&gt;,  &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;employee&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;}
  ]
}&lt;/pre&gt;
&lt;div class="zeroclipboard-container"&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p dir="auto"&gt;The &lt;code&gt;const&lt;/code&gt; field MAY otherwise be used for any other purpose. The binary decoder MAY skip encoding and decoding a field with a &lt;code&gt;const&lt;/code&gt; attribute and instead always return the constant value for the field similar to how the &lt;code&gt;default&lt;/code&gt; field is handled. The &lt;code&gt;const&lt;/code&gt; value overrides the &lt;code&gt;default&lt;/code&gt; value. During encoding, the binary encoder SHOULD check that the field value matches the &lt;code&gt;const&lt;/code&gt; value and MAY fail encoding if it does not.&lt;/p&gt;
&lt;div class="markdown-heading" dir="auto"&gt;
&lt;h3 class="heading-element" dir="auto" tabindex="-1"&gt;Feature 7: Document root records&lt;/h3&gt;
&lt;a id="user-content-feature-7-document-root-records" class="anchor" href="#feature-7-document-root-records" aria-label="Permalink: Feature 7: Document root records"&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p dir="auto"&gt;Avro schemas are defined as a single record or enum type at the top level or as a top-level type union. JSON documents, however, may have top-level arrays and maps. Without changing the fundamental Avro schema model, the plain JSON encoding mode uses an annotation on &lt;code&gt;array&lt;/code&gt; and &lt;code&gt;map&lt;/code&gt; types defined inside &lt;code&gt;record&lt;/code&gt; types to allow for top-level arrays and maps in the JSON document.&lt;/p&gt;
&lt;p dir="auto"&gt;The annotation is a boolean flag named &lt;code&gt;root&lt;/code&gt; that is set to &lt;code&gt;true&lt;/code&gt; on one record field's array or map type. The &lt;code&gt;root&lt;/code&gt; flag is only defined for &lt;code&gt;array&lt;/code&gt; and &lt;code&gt;map&lt;/code&gt; types. If the &lt;code&gt;root&lt;/code&gt; flag is present and has the value &lt;code&gt;true&lt;/code&gt;, the enclosing &lt;code&gt;record&lt;/code&gt; type MUST have exactly this one field.&lt;/p&gt;
&lt;p dir="auto"&gt;Given a JSON document with a top-level array like this:&lt;/p&gt;
&lt;div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto"&gt;
&lt;pre&gt;[
  {&lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Alice&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"age"&lt;/span&gt;: &lt;span class="pl-c1"&gt;42&lt;/span&gt;},
  {&lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Bob&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"age"&lt;/span&gt;: &lt;span class="pl-c1"&gt;43&lt;/span&gt;}
]&lt;/pre&gt;
&lt;div class="zeroclipboard-container"&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p dir="auto"&gt;The Avro schema would be defined as follows:&lt;/p&gt;
&lt;div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto"&gt;
&lt;pre&gt;{
  &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;record&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;PersonDocument&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="pl-ent"&gt;"fields"&lt;/span&gt;: [
    {
      &lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;persons&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
      &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: {
        &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;array&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
        &lt;span class="pl-ent"&gt;"root"&lt;/span&gt;: &lt;span class="pl-c1"&gt;true&lt;/span&gt;,
        &lt;span class="pl-ent"&gt;"items"&lt;/span&gt;: {
          &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;record&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
          &lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;PersonRecord&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
          &lt;span class="pl-ent"&gt;"fields"&lt;/span&gt;: [
            {&lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;name&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;string&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;},
            {&lt;span class="pl-ent"&gt;"name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;age&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;int&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;}
          ]          
        }
      }
    }
  ]
}&lt;/pre&gt;
&lt;div class="zeroclipboard-container"&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p dir="auto"&gt;When the JSON decoder encounters a top-level array or map, it MUST match the array or map to the field with the &lt;code&gt;root&lt;/code&gt; flag set to &lt;code&gt;true&lt;/code&gt;. When the &lt;code&gt;root&lt;/code&gt; flag is present on a field, the JSON encoder MUST yield the encoding of the field as the encoding of the entire record. The JSON encoder MUST fail if the &lt;code&gt;root&lt;/code&gt; flag is set to &lt;code&gt;true&lt;/code&gt; and if there is more than one field in the record.&lt;/p&gt;
&lt;p dir="auto"&gt;When such a record type is used as a field type inside another record, it consequently is always represented equivalent to a &lt;code&gt;map&lt;/code&gt; or &lt;code&gt;array&lt;/code&gt; type in the JSON document.&lt;/p&gt;
&lt;p dir="auto"&gt;In &lt;a href="#type-structure-matching"&gt;type structure matching&lt;/a&gt; scenarios, a set &lt;code&gt;root&lt;/code&gt; on a &lt;code&gt;map&lt;/code&gt; type causes the record type to be a candidate for the type matching of JSON &lt;code&gt;object&lt;/code&gt; values. The &lt;code&gt;root&lt;/code&gt; flag on an &lt;code&gt;array&lt;/code&gt; type causes the record type to be a candidate for the type matching of JSON &lt;code&gt;array&lt;/code&gt; values.&lt;/p&gt;
&lt;p dir="auto"&gt;The Avro binary encoding is not functionally affected by this feature, but the structural constraint imposed by the &lt;code&gt;root&lt;/code&gt; flag MAY be enforced by the encoder.&lt;/p&gt;
&lt;/article&gt;
&lt;p&gt;&lt;img src="https://vasters.com/clemens/content/binary/c4a79e5e-212f-4eda-bdb3-a2e310cf563f.webp" border="0"&gt;&lt;/p&gt;&lt;/div&gt;</description></item><item><trackback:ping>https://vasters.com/clemens/feed/trackback/day-20241110</trackback:ping><pingback:server>https://vasters.com/clemens/feed/pingback</pingback:server><pingback:target>https://vasters.com/clemens/post/day-20241110</pingback:target><dc:creator /><title>11/10/2024</title><guid isPermaLink="false">https://vasters.com/clemens/post/day-20241110</guid><link>https://vasters.com/clemens/2024/11/10</link><pubDate>Sun, 10 Nov 2024 00:00:00 GMT</pubDate><description>&lt;div&gt;&lt;div class="dasblog-dayentry"&gt;&lt;a style="margin-right:2ch" href="https://vasters.com/clemens/post/064c0875-1c38-4d6a-9a88-9f1cfecff8f0"&gt;#&lt;/a&gt;&lt;p&gt;Looking forward to the next season of Andor: &amp;nbsp;&lt;/p&gt;
&lt;p&gt;https://variety.com/2024/tv/news/andor-season-2-release-date-rogue-one-prequel-1235812153/&lt;/p&gt;&lt;/div&gt;&lt;div class="dasblog-dayentry"&gt;&lt;a style="margin-right:2ch" href="https://vasters.com/clemens/post/87317cf3-91f3-4e5a-b369-f2447542bd62"&gt;#&lt;/a&gt;&lt;p&gt;&lt;a href="https://www.reddit.com/r/csharp/comments/1gmfum0/comment/lwdw8ng/?utm_source=share&amp;amp;utm_medium=web3x&amp;amp;utm_name=web3xcss&amp;amp;utm_term=1&amp;amp;utm_content=share_button" target="_blank" rel="noopener"&gt;Reply in a Reddit thread on legitimate uses of returning "object" in C#&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;div class="dasblog-dayentry"&gt;&lt;a style="margin-right:2ch" href="https://vasters.com/clemens/post/d2334884-0e4d-4db0-b54e-22a2006decd3"&gt;#&lt;/a&gt;&lt;p&gt;https://bsky.app/profile/clemens.vasters.com/post/3lalmnd4r2c2s&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;</description></item><item xml:lang="en-us"><trackback:ping>https://vasters.com/clemens/feed/trackback/04d1463a-f595-4289-a5d7-1bd34629c8d6</trackback:ping><pingback:server>https://vasters.com/clemens/feed/pingback</pingback:server><pingback:target>https://vasters.com/clemens/post/04d1463a-f595-4289-a5d7-1bd34629c8d6</pingback:target><dc:creator /><title>A semantic identifier for occurrences: CloudEvent "type" </title><guid isPermaLink="false">https://vasters.com/clemens/post/04d1463a-f595-4289-a5d7-1bd34629c8d6</guid><link>https://vasters.com/clemens/2024/11/09/a-semantic-identifier-for-occurrences-cloudevent-type</link><pubDate>Sat, 09 Nov 2024 00:55:33 GMT</pubDate><description>&lt;div&gt;&lt;p&gt;In today's&amp;nbsp;&lt;a href="https://xregistry.io" target="_blank" rel="noopener"&gt;xRegistry WG&lt;/a&gt; Friday meeting we had a debate about the relationship between the message identifier (&lt;code&gt;messageid&lt;/code&gt;) that uniquely identifies a metadata template for a &lt;a href="https://cloudevents.io"&gt;CloudEvent&lt;/a&gt; (if that is the chosen&amp;nbsp;&lt;a href="https://github.com/xregistry/spec/blob/main/message/spec.md#metadata-envelopes" target="_blank" rel="noopener"&gt;envelope format&lt;/a&gt;) and the CloudEvent &lt;code&gt;type&lt;/code&gt;&amp;nbsp;attribute.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/xregistry/spec/blob/main/message/spec.md#message-definitions" target="_blank" rel="noopener"&gt;In the message Registry spec we recommend for those two identifiers to be the same&lt;/a&gt;; the example below shows this:&lt;/p&gt;
&lt;pre&gt;"&lt;span style="background-color: rgb(241, 196, 15);"&gt;Contoso.MotorVehicle.OilTemperatureThresholdExceeded&lt;/span&gt;": {
    "description": "Alarm event for when the oil temperature exceeds a threshold",
    "envelope": "CloudEvents/1.0",
    "envelopemetadata": {
        "id": { "required": true },
        "&lt;span style="background-color: rgb(241, 196, 15);"&gt;type&lt;/span&gt;": {
            "value": "&lt;span style="background-color: rgb(241, 196, 15);"&gt;Contoso.MotorVehicle.OilTemperatureThresholdExceeded&lt;/span&gt;",
            "description": "Event raised when oil temperature exceeds a set threshold"
        },
        "source": {
            "type": "uritemplate",
            "description": "source of the event",
            "value": "{vehicleid}/{componentid}"
        },
        "subject": {
            "type": "string",
            "description": "identifier of the temperature alarm"
        },
        "datacontenttype": {
            "value": "application/vnd.apache.avro+plainjson"
        },
        "time": { "required": true }
    },
    "schemaformat": "Avro/1.11.1",
    "schemauri": "#/schemagroups/Contoso.MotorVehicle/schemas/Contoso.MotorVehicle.OilTemperatureThresholdExceededEventData"
}&lt;/pre&gt;
&lt;p&gt;We believe that is the right choice for 90% of the cases, but it's a recommendation and not a requirement since there are cases where the two identifiers will be different. The discussion below will be interesting to CloudEvent users even if you don't care about xRegistry at the moment.&lt;/p&gt;
&lt;h3&gt;What does the CloudEvents &lt;code&gt;&lt;a href="https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#type"&gt;type&lt;/a&gt;&lt;/code&gt; attribute mean?&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;type&lt;/code&gt; attribute of a CloudEvent is an identifier of the kind of occurrence, the thing that happened that the event reports about. A database record was added, a river level gauge reading was made, the oil temperature of a motor exceeded a threshold value. The &lt;code&gt;type&lt;/code&gt; identifies those semantics.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;type&lt;/code&gt; is not coupled to a specific payload schema or schema version or schema format or data encoding. That is why the CloudEvent has the &lt;code&gt;dataschema&lt;/code&gt; and &lt;code&gt;datacontenttype&lt;/code&gt; attributes to individually qualify these aspects.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;type&lt;/code&gt;&amp;nbsp;is, however, supposed to be coupled to stable semantics. That is to say that when you define an event &lt;code&gt;type &lt;/code&gt;together with an initial payload, it's allowed for the payload to be refined over time by adding more information (since you can convey this via &lt;code&gt;dataschema&lt;/code&gt;) and it's also allowed to encode the information differently (since you can convey this via &lt;code&gt;datacontenttype&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;It's not allowed for the semantic essence of event to change under a given &lt;code&gt;type&lt;/code&gt;. The event still needs to report about the same kind of occurrence. Any breaking change, omitting formerly required information, is a semantic change and ought not to be permitted within a &lt;code&gt;type&lt;/code&gt;. If the semantics change, you &lt;em&gt;must&lt;/em&gt; introduce a new &lt;code&gt;type&lt;/code&gt; and you may indeed have to report the same occurrence once per any existing and newly introduced &lt;code&gt;type&lt;/code&gt;&amp;nbsp;if you make such a choice.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;We did not introduce "event type versions" as an easy switch in CloudEvents. We specifically wanted to put up a high bar for breaking changes. Distributed systems are hard enough while being disciplined about sticking to promises made. They turn into chaos if breaking promises is easy. We effectively mandate that a breaking change is signaled by a whole new &lt;code&gt;type&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now, I work with quite a few developers absolutely obsessed with precision and I know that "&lt;em&gt;semantic identifier of an occurrence&lt;/em&gt;" freaks them out as a concept because it's kinda wobbly. But the lack of specificity around the expression of the event semantics in terms of encodings and schemas is intentional because only that enables eventual evolution. Today, JSON encoding is overwhelmingly the favorite way to move event data, but tomorrow the fashion may change. The encoding choice changing, and with it the schema format required to drive that encoding, does not invalidate the semantic of the event. The the oil temperature of the motor &lt;em&gt;still &lt;/em&gt;exceeds its threshold value, even if the expression of it changes.&lt;/p&gt;
&lt;h3&gt;xRegistry message definitions&lt;/h3&gt;
&lt;p&gt;xRegistry aims to be a catalog for messaging and eventing, &lt;a href="https://github.com/xregistry/spec/blob/main/endpoint/spec.md"&gt;organizing endpoints&lt;/a&gt; for discovery, &lt;a href="https://github.com/xregistry/spec/blob/main/schema/spec.md" target="_blank" rel="noopener"&gt;organizing data schemas&lt;/a&gt; for sharing validation and serialization metadata, and &lt;a href="https://github.com/xregistry/spec/blob/main/message/spec.md" target="_blank" rel="noopener"&gt;organizing message metadata&lt;/a&gt; to declare "contracts" for communication channels.&lt;/p&gt;
&lt;p&gt;You can think of a message definition like the one shown above as a set of constraints (or a template) for an event. The definition above defines a specific expression of a CloudEvent of &lt;code&gt;type &lt;/code&gt;&lt;em&gt;Contoso.MotorVehicle.OilTemperatureThresholdExceeded.&amp;nbsp;&lt;/em&gt;The definition references an Apache Avro schema (not shown) and mandates for the encoding to be "&lt;a href="https://github.com/clemensv/avrotize/blob/master/avrojson.md" target="_blank" rel="noopener"&gt;vnd.apache.avro+plainjson&lt;/a&gt;" via a constraint of the &lt;code&gt;datacontenttype &lt;/code&gt;attribute.&lt;/p&gt;
&lt;p&gt;That is, however, just one way how one might to express this event in a message. You could have an alternate representation using Protobuf3.&amp;nbsp; &amp;nbsp;&lt;/p&gt;
&lt;pre&gt;"&lt;span style="background-color: rgb(241, 196, 15);"&gt;Contoso.MotorVehicle.OilTemperatureThresholdExceeded.&lt;span style="background-color: rgb(185, 106, 217);"&gt;Proto3&lt;/span&gt;&lt;/span&gt;": {
    "description": "Alarm event for when the oil temperature exceeds a threshold",
    "envelope": "CloudEvents/1.0",
    "envelopemetadata": {
        "id": { "required": true },
        "&lt;span style="background-color: rgb(241, 196, 15);"&gt;type&lt;/span&gt;": {
            "value": "&lt;span style="background-color: rgb(241, 196, 15);"&gt;Contoso.MotorVehicle.OilTemperatureThresholdExceeded&lt;/span&gt;",
            "description": "Event raised when oil temperature exceeds a set threshold"
        },
        "source": {
            "type": "uritemplate",
            "description": "source of the event",
            "value": "{vehicleid}/{componentid}"
        },
        "subject": {
            "type": "string",
            "description": "identifier of the temperature alarm"
        },
        "datacontenttype": {
            "value": "application/vnd.google.protobuf.v3"
        },
        "time": { "required": true }
    },
    "schemaformat": "Protobuf/3",
    "schemauri": "#/schemagroups/Contoso.MotorVehicle/schemas/Contoso.MotorVehicle.OilTemperatureThresholdExceededEventData.Proto3"
}&lt;/pre&gt;
&lt;p&gt;This definition is semantically identical as it shared the event type. Once you've deserialized the event into memory, the difference between the versions that flowed as Protobuf and the one that flowed as Avro-defined JSON should vanish completely if the schemas are, as they should, expressing semantically identical data structures.&lt;/p&gt;
&lt;p&gt;In a constellation where we want to flow events in different encodings, we will therefore have multiple definitions that have distinct message definition identifiers (&lt;code&gt;messageid&lt;/code&gt;), but which refer to the same &lt;code&gt;type&lt;/code&gt; as they express the same semantics. A basic test for whether the structurally expressed semantics match across the variants of the event is whether the schemas for the respective encodings can be mapped to the same in-memory data structure easily.&lt;/p&gt;
&lt;p&gt;The specificity of a message definition in that it ties together several constraints also means that it's not versionable per-se; message types have variants, not versions. Consequently, xRegistry does not version message definitions, different from how it handles data schemas.&lt;/p&gt;
&lt;p&gt;If you change the composition of the constraints, you create a new definition. That is the case because if you ever produced a message based on the given set of constraints, another party using the catalog needs to be able to have the definition available to match against, side-by-side with all other variants. If a message arrives with&amp;nbsp;&lt;code&gt;type&lt;/code&gt;&amp;nbsp;&lt;em&gt;Contoso.MotorVehicle.OilTemperatureThresholdExceeded &lt;/em&gt;and &lt;code&gt;datacontenttype&lt;/code&gt;&amp;nbsp;&lt;em&gt;application/vnd.google.protobuf.v3, &lt;/em&gt;having both of the definitions above available concurrently allows matching and subsequently processing according to the metadata/constraints of the second (&lt;em&gt;*.Proto3&lt;/em&gt;) one.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The application platform layers that deal with dispatching and deserialization or channel selection and serialization will distinguish events by&amp;nbsp;&lt;code&gt;messageid&lt;/code&gt; and, in the dispatcher case, pattern-match incoming events against the concurrently available message definitions to find one specific match. The application layers above will distinguish events by their CloudEvents &lt;code&gt;type&lt;/code&gt; as all alternate definitions and their alternate wire representations ought to yield compatible events to the application after processing.&amp;nbsp;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I wrote this down primarily to capture today's WG discussion, but I hope you also find this useful as a CloudEvents practitioner.&lt;/p&gt;
&lt;p&gt;[Note: A few links in this document don't deep-link to where they should; that's due to a bug in my fork of the blog engine that I'll fix shortly]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://vasters.com/clemens/content/binary/c4afc99a-aaac-462c-ac1f-b611e7ce9cc4%20(1).webp" border="0"&gt;&lt;/p&gt;&lt;/div&gt;</description><category>cloudevents</category><category>cncf</category><category>xregistry</category></item></channel></rss>