<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Modern JSON Schema and APIs]]></title><description><![CDATA[Explorations and explanations of OpenAPI and JSON Schema from a co-author of the specifications.]]></description><link>https://modern-json-schema.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1667676345585/C8hQ3_utQ.png</url><title>Modern JSON Schema and APIs</title><link>https://modern-json-schema.com</link></image><generator>RSS for Node</generator><lastBuildDate>Wed, 15 Apr 2026 19:29:14 GMT</lastBuildDate><atom:link href="https://modern-json-schema.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Analyzing the OpenAPI Tooling Ecosystem]]></title><description><![CDATA[Welcome to a new series of posts that will take you on a visual journey through the OpenAPI Specification (OAS) and its tooling ecosystem!
Why diagram the OAS ecosystem?
As part of the efforts to design OAS 3.2 and 4.0 “Moonwalk”, I wanted to figure ...]]></description><link>https://modern-json-schema.com/analyzing-the-openapi-tooling-ecosystem</link><guid isPermaLink="true">https://modern-json-schema.com/analyzing-the-openapi-tooling-ecosystem</guid><category><![CDATA[OpenApi]]></category><category><![CDATA[REST API]]></category><category><![CDATA[http]]></category><category><![CDATA[APIs]]></category><category><![CDATA[json-schema]]></category><category><![CDATA[API development ]]></category><category><![CDATA[API Design]]></category><category><![CDATA[Testing]]></category><category><![CDATA[tools]]></category><category><![CDATA[api tools]]></category><dc:creator><![CDATA[Henry Andrews]]></dc:creator><pubDate>Sat, 21 Sep 2024 19:05:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1726875084520/c8730c2a-f4aa-47df-9dad-ae5b8c9b7013.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome to a new series of posts that will take you on a visual journey through the OpenAPI Specification (OAS) and its tooling ecosystem!</p>
<h1 id="heading-why-diagram-the-oas-ecosystem">Why diagram the OAS ecosystem?</h1>
<p>As part of the efforts to design OAS 3.2 and 4.0 “<a target="_blank" href="https://www.openapis.org/blog/2023/12/06/openapi-moonwalk-2024">Moonwalk</a>”, I wanted to figure out how different sorts of tools work with the OAS. Moonwalk is an opportunity to re-think everything, and I want that re-thinking to make it easier to design, implement and maintain tools. We also want 3.2 to be an incremental step towards Moonwalk, so figuring out what improvements we can make to align with the needs of tools while maintaining strict compatibility with OAS 3.1 is also important.</p>
<p>To do that, we need to understand how the OAS-based tooling ecosystem works, and how the various tools relate to the current OAS version, 3.1. This eventually led me to create two groups of diagrams: One about the architecture of OAS-based tools, and one about the many objects and fields defined by the OAS and how they relate to what tools need to do. But this was not a simple process!</p>
<h2 id="heading-oas-tools-do-stuff">OAS tools do… stuff?</h2>
<p>I was surprised at how difficult it was to find patterns in tool design and OAS usage. I thought I could go look at how tools were categorized on sites that list them, figure out what each category needs, and see how that aligns with the current and proposed future OAS versions. I was wrong. Looking the OpenAPI Initiative’s own <a target="_blank" href="https://tools.openapis.org/">tools site</a> reveals categories that often overlap and tools that don’t map cleanly to categories.</p>
<p>One problem is that many “tools” aren’t so much OAS implementations as they are applications that include some OAS-based functionality. So maybe “tool” or “application” isn’t the right granularity for this research. Really, there are different tasks that can be done with an <a target="_blank" href="https://learn.openapis.org/specification/structure.html">OpenAPI Description (OAD)</a>, and each OAS-based tool, application, or library does at least one such task.</p>
<h2 id="heading-what-if-one-tool-did-it-all">What if one tool did it all?</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726866122677/93bdf607-059e-46da-9e27-e369cc679df3.webp" alt="Meme generated based on Allie Brosh's &quot;DO ALL THE THINGS!&quot; image from Hyperbole and a Half, captioned &quot;IMPLEMENT ALL THE TASKS!!!&quot; with the figure holding the OpenAPI logo in her upraised hand" class="image--center mx-auto" /></p>
<p>I started thinking about all of the tasks, and how they relate to each other. The goal is not to <em>really</em> create a monolithic mega-tool architecture. Not all tasks happen on the same system, or at the same time in the development process. But it would help to understand which tasks directly relate to each other, which don’t, and what the interfaces among them ought to be.</p>
<h1 id="heading-an-idealized-architecture">An idealized architecture</h1>
<p>After several iterations with valuable feedback from the regular OAS working group calls, here is what I came up with (based on OAS 3.1 plus ideas for 3.2 and Moonwalk):</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728840775960/54e48f3f-1a33-4e6a-ba3a-3f65cc7d69b1.webp" alt class="image--center mx-auto" /></p>
<p>The first thing to notice is the that this “idealized architecture” breaks down into three main purposes or functional areas:</p>
<ul>
<li><p><strong>Parsing libraries</strong>: The foundation on which all other tools are built</p>
</li>
<li><p><strong>OAD tools</strong>: These work with <a target="_blank" href="https://learn.openapis.org/specification/structure.html">OpenAPI Descriptions</a> and their constituent documents</p>
</li>
<li><p><strong>API tools</strong>: These work with the API that the OAD describes but (mostly) aren’t concerned with the mechanics of OAD documents and references</p>
</li>
</ul>
<h2 id="heading-color-coding-and-accessibility">Color coding and accessibility</h2>
<p>Before we look at the three purposes, let’s talk about how I’m using color in these diagrams:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726621444272/609037a4-5752-412a-a76a-593e95877ea4.webp" alt="A labeled grid of the colors named in the paragraph below the image" /></p>
<p>The colors here, named “pale grey”, “light yellow”, “pink”, “light cyan”, “pear”, “olive”, “light blue”, “orange”, and “mint”, are <a target="_blank" href="https://personal.sron.nl/~pault/#fig:scheme_light">a set designed by Paul Tol</a> to work well with dense grids of information labeled with black text, regardless of color vision ability.</p>
<p>I’ll always use these names (minus the “pale” and “light” qualifiers) to talk about the colors in these diagrams. Every diagram will include the color names so that no one has to guess which color is which, and all diagrams use the same colors to mean the same general things:</p>
<ul>
<li><p><strong>Gray</strong>: Documents and metadata</p>
</li>
<li><p><strong>Yellow</strong>: References and implicit connections</p>
</li>
<li><p><strong>Pink</strong>: Parsing</p>
</li>
<li><p><strong>Cyan</strong>: Interface modeling</p>
</li>
<li><p><strong>Pear</strong>: Runtime data validation</p>
</li>
<li><p><strong>Olive</strong>: Extended validation</p>
</li>
<li><p><strong>Blue</strong>: Data encoding</p>
</li>
<li><p><strong>Orange</strong>: HTTP modeling</p>
</li>
<li><p><strong>Mint</strong>: API documentation</p>
</li>
</ul>
<p>As we compare diagrams about tools with diagrams about the spec (which you’ll see in future posts), we will hope that consistent use of color will show clear alignment between these two perspectives. Wherever they do not, we probably have some work to do.</p>
<h2 id="heading-parsing-libraries">Parsing libraries</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726869119572/ab1dc05f-23f5-4f8d-a169-02ed6678d475.webp" alt="The &quot;Parsing Libraries&quot; region of the previous diagram, containing three horizontal blocks:  A grey block &quot;Document Interface&quot; across the entire bottom, a yellow &quot;URI Reference and Implicit Connection Resolver&quot; block above it, and an &quot;API Description API (ADA)&quot; block above and wrapping the yellow block, extending most of the width except the far left.  Arrows enter from the top edge pointing to the pink block except the left-most one to the grey block." class="image--center mx-auto" /></p>
<p>The most fundamental functional area, “Parsing Libraries”, consists of a stack of wide blocks stretching across the bottom. From the color code, you can see that these blocks deal with the low-level document interface (grey), resolving references and implicit connections (yellow), and parsing (pink). “Implicit connections” is a term we’re introducing in OAS 3.0.4 and 3.1.1 that encompasses things like mapping Security Requirement Object keys to Security Scheme Object names under the <code>securitySchemes</code> field of the Components Object.</p>
<p>Every tool, application, or library that works with OADs or the APIs that they describe has to parse OADs and do at least some resolution of internal connections. While some references can be preprocessed out, others cannot, nor can any of the implicit connections. We’ll explore these challenges, as well as the interactions between the grey, yellow, and pink blocks, more deeply in future posts.</p>
<h3 id="heading-the-api-description-api-ada">The API Description API (ADA)</h3>
<p>For now, the most important thing is that the upper pink block, which I’m tentatively calling the “API Description API (ADA)”, is intended to provide a clean interface to the parsed and resolved OAD that insulates tools from the complexities of document managing and referencing. This ADA would be somewhat akin to <a target="_blank" href="https://dom.spec.whatwg.org/">the DOM</a>. There are, however, fundamental differences between OADs and web pages, so the analogy is not exact.</p>
<p>We’ve decided that we want to have an ADA in Moonwalk. It’s an open question as to whether it would be worthwhile to start defining it in 3.x. Would 3.x tools (or at least parsing libraries) would start supporting it? If you have thoughts on that concern, or on whether “ADA” is a good name, we’d like to hear from you!</p>
<h2 id="heading-oad-tools">OAD tools</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726939103049/fe73382e-c497-41cb-8f88-aaa11101bd74.webp" alt="The &quot;OAD Tools&quot; region from the first diagram.  Pink boxes labeled &quot;OAD Generator&quot;, &quot;OAD Editor&quot;, &quot;OAD Linter, &quot;OAD Validator&quot;, &quot;Format Translator&quot;, &quot;Arazzo Processor&quot;, and &quot;Overlay Processor&quot; have pink arrows out that merge downwards, then split to a pink &quot;Semantic Access&quot; and grey &quot;Structural Access&quot; arrows, both exiting the image at the bottom" class="image--center mx-auto" /></p>
<p>The first change I would make to sites that classify OpenAPI tools would be to separate the tools that work with OADs from the tools the work with APIs.</p>
<p>These are fundamentally different use cases and mindsets, and they have different requirements when it comes to interacting with OADs. The blocks in this area are colored pink because they are primarily concerned with the structure of the OAD. The description semantics inform what can or should be done with the OAD, but it is the OAD rather than the described API that is the focus of these tools.</p>
<p>The left column includes OAD editors (including IDE plugins), validators, linters, and generators (producing an OAD from code). The right column includes tools connecting the OAD with other specifications, including <a target="_blank" href="https://spec.openapis.org/">the OpenAPI Initiative’s Arazzo and (forthcoming) Overlays specifications</a>. The right column also contains translators from other formats such as RAML, or from formats that offer an alternative syntax that “compiles” down to an OAD.</p>
<p>Semantic operations, such as a linting rule that applies to every Response Object, no matter its location, benefit from <em>semantic access</em> via the ADA (pink downward arrow). Structural operations, such as an overlay that inserts a field into each object matching a <a target="_blank" href="https://www.rfc-editor.org/rfc/rfc9535.html">JSON Path</a> applied to a specific document (or anything that requires writing to documents), benefit from <em>structural access</em> via the underlying document interface (grey downward arrow).</p>
<h2 id="heading-api-tools">API Tools</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726872418804/6fab8355-3050-426e-881b-385ec76c1805.webp" alt="&quot;API Tools&quot;: Flow of HTTP requests/responses through tasks.  Major boxes left to right after an &quot;end user &quot;emoji: &quot;API Documentation&quot; (mint), &quot;Data Interface Modeler and Validator&quot; (cyan), &quot;Data Encoder and Decoder&quot; (blue), &quot;HTTP Parser and Serializer&quot; (orange).  Arrows connecting boxes across the top (client) and bottom (server) show request/response flow, with cyan &quot;API Client Code&quot; and &quot;API Server Code&quot; (where the arrows U-turn) labels to the left of the cyan box.  Each box has an arrow down towards the ADA.  See later images for details of boxes above each main box, and flow labels on right-side client and left-side server arrows." class="image--center mx-auto" /></p>
<p>Now that we’ve accounted for shared parsing tasks and OAD-specific tools, we’re ready to examine how the OAS supports working with an API. We’ll start on the left edge where our hypothetical end user is looking at an interactive documentation site that includes a test interface to send requests and display the resulting responses.</p>
<p>While our discussion will follow the progress of a request on the client side, the steps are reversed to parse, decode, and validate the request on the server, and then run again on the server to validate, encode, and assemble a response, which is parsed, decoded, validated, and displayed to the end user on the client side.</p>
<h3 id="heading-api-documentation-mint">API Documentation (mint)</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726942251208/babb475c-c3f9-4c6c-a833-af7b4029abfc.webp" alt="&quot;API Documentation&quot; (mint): upper boxes &quot;Markdown Rendering&quot;, &quot;PDF Rendering&quot;, &quot;HTML Rendering&quot;; flow: &quot;input to request&quot; out, &quot;response output&quot; in." class="image--center mx-auto" /></p>
<p>Documentation is produce by mint-colored blocks that use the ADA to walk through the whole OAD, organize the information for human consumption, and render it to the end user in some format. Different formats could be handled as plugins in an extensible architecture, as shown above the main mint-colored block.</p>
<p>The API documentation block is the only one that looks at every part of the OAD that is visible through the ADA. Separating docs processing into its own block allows other blocks to ignore the fields that <em>only</em> impact documentation. This might influence how the ADA is designed.</p>
<p>If the documentation is interactive, then it would incorporate an interface generated by the next block that can take the appropriate session or operation input and render the results. The mint blocks are concerned with rendering that interface, but not with defining it.</p>
<h3 id="heading-interface-modeling-and-validation-cyan-pear-and-olive">Interface Modeling and Validation (cyan, pear, and olive)</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726942240345/0471a999-6f37-470b-a66c-2ebcba606e11.webp" alt="&quot;Data Interface Modeler and Validator&quot;: upper boxes &quot;CLI Interface&quot;, &quot;Web Form Generation&quot;, &quot;Client Code Generation&quot;, &quot;Server Code Generation&quot; (all cyan), &quot;Data Validation&quot; (pear), and &quot;Extended Validation&quot; (olive); flow: (client) &quot;validated data&quot; out, &quot;decoded data&quot; in; (server) &quot;handler input&quot; out, u-turn to &quot;handler output&quot; in." class="image--center mx-auto" /></p>
<p>Following the arrow to the right, we reach the API client code. The boundary between the three differently-colored types of blocks within this larger area is somewhat ambiguous, and varies depending on the programming language(s) and types of tools being used.</p>
<p><strong><em>Interface definition (cyan)</em></strong></p>
<p>Cyan represents the static code-level (as opposed to HTTP-level) interface to the API. The diagram shows how there might be several form factors for this interface stacked in the left column above the main cyan block: Code libraries on the client and server, or a web or CLI interface for interactive documentation or manual testing. Such an interface might be very generic, or it might be custom-generated with elaborate static type-checking.</p>
<p><strong><em>Runtime data validation (pear)</em></strong></p>
<p>The pear-colored module is for runtime data validation, verifying constraints that are not inherent in the interface’s type-checking but only depend on the data passed to that interface. It's mostly synonymous with JSON Schema validation, although not entirely as we'll see when we color code individual fields in the next post.</p>
<p><strong><em>Extended validation (olive)</em></strong></p>
<p>The olive-colored module is for validation such as <code>readOnly</code> that requires additional context about how the data is being used, which often builds on the runtime validation by using <a target="_blank" href="https://www.ietf.org/archive/id/draft-bhutton-json-schema-01.html#name-collecting-annotations">annotations</a>.</p>
<p><strong><em>A confusing boundary</em></strong></p>
<p>As noted, the boundary between these three colors is ambiguous. <a target="_blank" href="https://modern-json-schema.com/json-schema-is-a-constraint-system">JSON Schema is not a data definition system</a>, and was not designed with a clear division between static data types (cyan) and runtime constraints (pear) in mind. Languages support differing type-checking paradigms, tools have variable levels of support for classes or other complex structures, and "code generation" can be taken to the extreme of generating a custom function for each JSON Schema.</p>
<p>Additionally, <code>format</code> values are sometimes handled as static types (cyan), sometimes as runtime validation (pear), and sometimes as annotation-based validation (olive).</p>
<p>All of this overlap and ambiguity is a major challenge for tooling vendors, an one we’ll examine in detail in a future post.</p>
<h3 id="heading-data-encoding-and-decoding-blue">Data Encoding and Decoding (blue)</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726942225013/bb3564a6-c528-4092-88f5-c29ca973d4ab.webp" alt="&quot;Data Encoding and Decoding&quot;: upper boxes &quot;JSON&quot;, &quot;YAML&quot;, &quot;XML&quot;, &quot;Plain Text&quot;, &quot;JSON Seq&quot;, &quot;Multipart&quot;, &quot;URL Encoded&quot; labeled &quot;media types&quot;; &quot;URL Path Variables&quot;, &quot;Cookies&quot;, &quot;RFC9110 Headers&quot;, &quot;Structured Headers&quot;, &quot;Other Headers&quot; labeled &quot;grammars&quot;;  flow: (client) &quot;encoded data&quot; out, &quot;parsed data&quot; in; (server) &quot;decoded data&quot; out, &quot;validated data&quot; in." class="image--center mx-auto" /></p>
<p>The code interface is defined in terms of JSON-compatible data structures. Encoding such a structure as an <code>application/json</code> request body is trivial. But validated data also needs to be mapped into other media types, and into various bits and pieces governed by other rules such as ABNF grammars.</p>
<p>In this diagram, I'm proposing a modular, extensible system to handle these encodings or translations. API innovation moves faster than specification development, and the OAS doesn’t currently have a good way to accommodate emerging data formats like JSON streams. We also haven’t ever addressed things like HTTP headers with complex structure.</p>
<p>Defining an extensible interface, where mappings to various targets could be defined in a <a target="_blank" href="https://github.com/OAI/OpenAPI-Specification/discussions/3771">registry</a> and supported with a plug-in architecture, would dramatically increase the flexibility of the OAS tooling ecosystem, as well as its responsiveness to innovation. It could also help us get the substantial complexity of the data encoding fields, which we’ll start to explore in the next post, under control.</p>
<h3 id="heading-http-modeling-orange">HTTP Modeling (orange)</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726942210619/725bec4e-97b3-4acf-95bb-4c1038f0a0cc.webp" alt="&quot;HTTP Parser and Serializer&quot;: upper boxes &quot;Auth Server Interactions&quot;, &quot;Requests&quot;, &quot;Responses&quot;, &quot;Runtime Expressions&quot;, &quot;Links&quot;, &quot;Callbacks&quot;, &quot;Webhooks&quot;; flow: u-turn &quot;http request/response in/out&quot; network transit on the right; (server) &quot;parsed data&quot; out and &quot;encoded data&quot; in on the left." class="image--center mx-auto" /></p>
<p>Finally, we reach the orange block that is takes the bits and pieces of encoded data and assembles them into HTTP messages (or parses them back out). We see on our diagram how data passes through this module as a request to be constructed, then back through on the server side where the request is parsed, handled, and returned as a response.</p>
<p>This area breaks down into three sub-areas: Server configuration (which provides the URL prefix for HTTP calls), security configuration (which might involve HTTP interactions with an auth server), and the actual API operations.</p>
<p>Much of this HTTP parsing and serialization can be handled by standard libraries, which can also help define us the exact border with the data encoding blocks. Our goal is to organize the OAS aspect of things, not to re-invent the wheel of HTTP and related technologies.</p>
<h1 id="heading-thats-a-pretty-picture-but-now-what">That’s a pretty picture, but now what?</h1>
<p>The next step is to analyze OAS 3.1 and the likely 3.2 proposals in detail and correlate the Objects and fields with this idealized architecture. That starts to show where we have mismatches between the spec and tools, and what we might want to do about them, which will be the subject of the next post.</p>
<p>However, one aspect of this diagram is already driving real work: This past week’s Moonwalk working group call featured a <a target="_blank" href="https://learn.openapis.org/glossary.html">TSC</a> member demo-ing a small ADA proof-of-concept. The idealized architecture may be theoretical, but its impacts on the future of the OAS are already very real.</p>
]]></content:encoded></item><item><title><![CDATA[Future-proofing your path from OpenAPI 3.0 to 3.1 and beyond!]]></title><description><![CDATA[The most popular version of the OpenAPI Specification (OAS) as of early 2024 is OAS 3.0. While adoption of OAS 3.1 is gaining steam, users whose needs are met by 3.0 or who want to wait for 3.1 support to mature are in no hurry to update. But softwar...]]></description><link>https://modern-json-schema.com/your-path-from-openapi-30-to-31-and-beyond</link><guid isPermaLink="true">https://modern-json-schema.com/your-path-from-openapi-30-to-31-and-beyond</guid><category><![CDATA[OpenApi]]></category><category><![CDATA[json-schema]]></category><category><![CDATA[REST API]]></category><category><![CDATA[APIs]]></category><category><![CDATA[swagger]]></category><category><![CDATA[API-First]]></category><dc:creator><![CDATA[Henry Andrews]]></dc:creator><pubDate>Tue, 20 Feb 2024 18:43:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1709757079739/3ec384bd-b779-4f41-923e-ce1e5fc1b41e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The most popular version of the OpenAPI Specification (OAS) as of early 2024 is <a target="_blank" href="https://spec.openapis.org/oas/v3.0.3">OAS 3.0</a>. While adoption of <a target="_blank" href="https://spec.openapis.org/oas/v3.1.0">OAS 3.1</a> is gaining steam, users whose needs are met by 3.0 or who want to wait for 3.1 support to mature are in no hurry to update. But software ecosystems never stand still.</p>
<p>What can 3.0 users do <em>now</em> to make the update to 3.1 easier, whether it is in the near or distant future? This is the first of a series of posts addressing that question, in which you will learn:</p>
<ul>
<li><p>the OAS road map and your possible update paths</p>
</li>
<li><p>schema re-use patterns that illustrate the how and why of future-proofing for 3.1</p>
</li>
<li><p>techniques to use in 3.0 to make it easier to quickly benefit from updating</p>
</li>
</ul>
<p>This post provides a high-level overview. The next few posts will get into more concrete details, including a guide to actually updating your API descriptions to 3.1.</p>
<h1 id="heading-the-oas-road-map">The OAS Road Map</h1>
<p><em><strong>Note:</strong> While I am very involved in the OpenAPI project, I do not speak for it! I am confident in the direction, but the details could change.</em></p>
<p>The key point of the proposed OpenAPI Specification road map are:</p>
<ul>
<li><p>All 3.x releases from 3.2 on will be 100% compatible with 3.1</p>
</li>
<li><p>The 3.2+ releases will be small and incremental</p>
</li>
<li><p>OAS 4.0 <a target="_blank" href="https://www.openapis.org/blog/2023/12/06/openapi-moonwalk-2024">"Moonwalk"</a> features will be backported to 3.2+ when possible</p>
</li>
</ul>
<p>OAS 3.1 is much bigger than 3.0, and slightly incompatible with it. While there were <a target="_blank" href="https://www.openapis.org/blog/2020/06/18/openapi-3-1-0-rc0-its-here">good reasons</a> for this, <strong>the newly proposed road map prioritizes painless updates from 3.1, rapid implementation of 3.2+, and an incremental path to 4.0.</strong></p>
<h1 id="heading-three-re-use-challenges">Three re-use challenges</h1>
<p>These challenges come from my experience with consulting clients who are working with complex data models, or are standardizing approaches across multiple APIs. If your API has a simple, self-contained data model, you may not have seen the difficulties, or may have easily worked around them. Even then, understanding these challenges will give you more design options to support your API's growth.</p>
<p>Our challenges are to:</p>
<ul>
<li><p>re-use object schemas while forbidding unknown properties</p>
</li>
<li><p>re-use collection schemas with different contents</p>
</li>
<li><p>recognize a standard component by a location-independent identifier</p>
</li>
</ul>
<p>Let's look at these in a bit more detail before talking about the solutions in OAS 3.1 and beyond.</p>
<h3 id="heading-object-re-use-and-unknown-properties">Object re-use and unknown properties</h3>
<p>This challenge is most likely to show up if you are trying to align your schemas with the behavior of strictly-typed object-oriented languages. Particularly if you have a complex class hierarchy. The problem is that</p>
<ol>
<li><p>re-using an object schema involves using <code>$ref</code> with <code>allOf</code>, <code>oneOf</code>, etc.</p>
</li>
<li><p>failing validation when an unexpected property is seen requires <code>additionalProperties: false</code></p>
</li>
<li><p>these two techniques cannot be used together<a class="post-section-overview" href="#ft1"><sup>[1]</sup></a></p>
</li>
</ol>
<pre><code class="lang-YAML"><span class="hljs-attr">components:</span>
  <span class="hljs-attr">schemas:</span>
    <span class="hljs-attr">extensibleBase:</span>
      <span class="hljs-attr">type:</span> <span class="hljs-string">object</span>
      <span class="hljs-attr">properties:</span>
        <span class="hljs-attr">foo:</span> {<span class="hljs-attr">type:</span> <span class="hljs-string">integer</span>}
    <span class="hljs-attr">sealedBase:</span>
      <span class="hljs-comment"># This schema fails if foo is present, because this</span>
      <span class="hljs-comment"># additionalProperties can't "see" the foo definition</span>
      <span class="hljs-attr">allOf:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">$ref:</span> <span class="hljs-string">"#/components/schemas/extensibleBase"</span>
      <span class="hljs-attr">additionalProperties:</span> <span class="hljs-literal">false</span>
</code></pre>
<h3 id="heading-re-using-collection-schemas">Re-using collection schemas</h3>
<p>In strictly-typed languages, structures like collections correspond to generics (Java, C#) or templates (C++). These programming idioms have concise syntax, but in OAS 3.0's version of JSON Schema, you need to duplicate some of the generic structure for each wrapped type:</p>
<pre><code class="lang-YAML"><span class="hljs-attr">components:</span>
  <span class="hljs-attr">schemas:</span>
    <span class="hljs-attr">collection:</span>
      <span class="hljs-attr">type:</span> <span class="hljs-string">object</span>
      <span class="hljs-attr">properties:</span>
        <span class="hljs-attr">metadata:</span>
          <span class="hljs-string">$ref:</span> <span class="hljs-string">"#/components/schemas/metadata"</span>
        <span class="hljs-attr">data:</span>
          <span class="hljs-attr">type:</span> <span class="hljs-string">array</span>
          <span class="hljs-attr">items:</span> {}   <span class="hljs-comment"># allow anything</span>
    <span class="hljs-attr">thing:</span>
      <span class="hljs-attr">type:</span> <span class="hljs-string">string</span>
    <span class="hljs-attr">thingCollection:</span>
      <span class="hljs-attr">allOf:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">$ref:</span> <span class="hljs-string">"#/components/schemas/collection"</span>
      <span class="hljs-comment"># Here we have to duplicate the path to the items</span>
      <span class="hljs-attr">properties:</span>
        <span class="hljs-attr">data:</span>
          <span class="hljs-attr">items:</span>
            <span class="hljs-string">$ref:</span> <span class="hljs-string">"#/components/schemas/thing"</span>
    <span class="hljs-attr">metadata:</span>
      <span class="hljs-comment"># Assume some object schema here for pagination, etc.</span>
</code></pre>
<p>The three extra keywords and nesting levels here aren't too burdensome. But with a more complex container and many wrapped types, it becomes fragile to maintain.<a class="post-section-overview" href="#ft2"><sup>[2]</sup></a></p>
<h3 id="heading-identifying-standard-components">Identifying standard components</h3>
<p>Some APIs need interoperability with industry standards.<a class="post-section-overview" href="#ft3"><sup>[3]</sup></a> For example, there are libraries for handling data that conforms to the GeoJSON standard (<a target="_blank" href="https://www.rfc-editor.org/rfc/rfc7946.html">RFC 7946</a>), which has standard JSON Schemas such as <a target="_blank" href="https://geojson.org/schema/Feature.json">https://geojson.org/schema/Feature.json</a> for a GeoJSON "feature." If you see <code>"$ref": "https://geojson.org/schema/Feature.json"</code> in <em>any</em> API, you know that you can use your GeoJSON library on that data.</p>
<p>OAS 3.0 describes reference URLs as <em>locators</em>, implying that tools should retrieve the target using the URL. However, not all tools support references to external documents. Even if they do, security policies, unreliable networks, or performance constraints can make them impractical or impossible to use. If you have to copy that GeoJSON schema somewhere else, code looking for the standard URL won't recognize the URL of the new location.</p>
<h2 id="heading-when-challenges-combine">When challenges combine...</h2>
<p>A workaround for the URL problem might be to compare the schemas instead of the references. However, experience shows that copies are often modified, for example to work around the other challenges. You might want a "strict" Feature schema that forbids unknown properties, and specializations of the <a target="_blank" href="https://geojson.org/schema/FeatureCollection.json">Feature Collection</a> schema with different extended or strict features. Even the most dedicated <a target="_blank" href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself">DRY</a> programmers will resort to copy-paste(-modify) if proper re-use is too hard.</p>
<h1 id="heading-challenges-on-the-road-map">Challenges on the Road Map</h1>
<p>So lets look at how our challenges are handled in each current or proposed release:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td></td><td>objects</td><td>collections</td><td>recognition</td></tr>
</thead>
<tbody>
<tr>
<td>3.0 (July 2017)</td><td>requires duplication</td><td>requires duplication</td><td>requires non-standard tool support</td></tr>
<tr>
<td>3.1 (Feb. 2021)</td><td><code>unevaluatedProperties</code></td><td><code>$dynamicAnchor</code> + <code>$dynamicRef</code>, with caveats</td><td>Schemas only: <code>$id</code> and/or <code>$anchor</code>, with caveats</td></tr>
<tr>
<td>3.2 (Mid-2024?)</td><td><code>unevaluatedProperties</code></td><td><code>$dynamicAnchor</code> + <code>$dynamicRef</code> (with clarifications?)</td><td><a target="_blank" href="https://github.com/OAI/sig-moonwalk/discussions/72#discussioncomment-8388906">possible backport of proposed <code>self</code> field</a> + JSON Pointer</td></tr>
<tr>
<td>4.0 (Dec. 2024?)</td><td><code>unevaluatedProperties</code></td><td><code>$dynamicAnchor</code> + <code>$dynamicRef</code></td><td><a target="_blank" href="https://github.com/OAI/sig-moonwalk/discussions/72">proposed <code>self</code> field + component name</a></td></tr>
</tbody>
</table>
</div><p>For re-using objects while forbidding unexpected properties, there's a <a target="_blank" href="https://json-schema.org/blog/posts/modelling-inheritance">solid, well-supported solution</a> in OAS 3.1.</p>
<p>In theory, <a target="_blank" href="https://json-schema.org/blog/posts/dynamicref-and-generics">collections are also solved in OAS 3.1</a>. In practice, the solution depends on keywords that are often not yet implemented, even by tools claiming 3.1 support. There was a similar lag in support for <code>discriminator</code> with past OAS versions.</p>
<p>Component recognition in OAS 3.1 only works for Schema Objects, and has similar keyword support challenges. Fortunately, this is likely to be thoroughly addressed in OAS 4.0, in a way that should be possible to backport to 3.x.</p>
<h1 id="heading-what-should-you-do-in-30">What should you do in 3.0?</h1>
<p>This post introduced the proposed road map and three re-use challenges. The next few posts will get into the concrete details of each challenge. But the basic pattern is the same for <em>any</em> use of 3.0 that will benefit from new features in 3.1</p>
<ol>
<li><p>Identify where you are working around limitations in 3.0, and why</p>
</li>
<li><p>Make sure your workarounds for each limitation are consistent and recognizable (and document them as best practices within your team)</p>
</li>
<li><p>If your API description is large, create an <code>x-</code> prefixed extension keyword for each workaround so that you (or an automated tool) can find them in the future</p>
</li>
</ol>
<p>For these three challenges, you won't <em>need</em> to change anything just to move to a newer OAS 3.x version. But taking advantage of the new features will make your API descriptions more robust and maintainable.</p>
<p>We'll take a concrete look at how that works for the object re-use case in the next post in this series.</p>
<hr />
<ol>
<li><p><span id="ft1"></span>For several years, the most common complaint about JSON Schema was this <code>additionalProperties: false</code> problem. The debate on how to solve it ran for more than 500 GitHub comments before we settled on <code>unevaluatedProperties</code>!</p>
</li>
<li><p><span id="ft2"></span>I first saw the need for this sort of feature in Cloudflare's pre-OpenAPI documentation system, <a target="_blank" href="https://github.com/cloudflare/doca">doca</a>, which extended JSON Hyper-Schema with a limited templating keyword for their standard response envelope. This directly inspired JSON Schema draft 2019-09's <code>$recursiveRef</code> and <code>$recursiveAnchor</code>, which evolved into 2020-12's <code>$dynamicRef</code> and <code>$dynamicAnchor</code>.  Cloudflare's <a target="_blank" href="https://developers.cloudflare.com/api/">current OAS 3.0.3 description</a> of course lacks that capability, so you will see lots of <code>"*-api-response-common"</code> components that repeat the same envelope with different contents. Once they move to 3.1, they should be able to shorten their description file considerably!</p>
</li>
<li><p><span id="ft3"></span>Special thanks to my client, the <a target="_blank" href="https://ogcapi.ogc.org/">Open Geospatial Consortium</a>, for motivating and supporting this post, and particularly for highlighting the component identification use case. As a result, I'll be using geospatial data-related examples in this and related posts.</p>
</li>
</ol>
<hr />
]]></content:encoded></item><item><title><![CDATA[Coming out of hibernation...]]></title><description><![CDATA[Sometimes you start a blog and right as you're getting going, life gets complicated. 2023 involved a lot of changes for me, including a shift in focus from the JSON Schema specification to the OpenAPI Initiative (not to be confused with OpenAI!). It'...]]></description><link>https://modern-json-schema.com/coming-out-of-hibernation</link><guid isPermaLink="true">https://modern-json-schema.com/coming-out-of-hibernation</guid><category><![CDATA[http api]]></category><category><![CDATA[OpenApi]]></category><category><![CDATA[json-schema]]></category><category><![CDATA[REST API]]></category><dc:creator><![CDATA[Henry Andrews]]></dc:creator><pubDate>Sun, 04 Feb 2024 18:30:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/_i8yKQx4bDA/upload/4c621cda89955e867c127e81487482d5.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Sometimes you start a blog and right as you're getting going, life gets complicated. 2023 involved a lot of changes for me, including a shift in focus from the JSON Schema specification to the OpenAPI Initiative (not to be confused with OpenAI!). It's taken over a year for things to settle enough for me to return to writing, but I'm returning now with a quick peak at what I'm working on now. I'll be exploring these topics more in future posts!</p>
<h1 id="heading-the-openapi-initiative">The OpenAPI Initiative</h1>
<p>2024 is shaping up to be a very exciting year for OpenAPI, and I'm very much involved in the work to define exactly what the year will look like.</p>
<h1 id="heading-openapi-release-landscape">OpenAPI Release Landscape</h1>
<p>The OpenAPI world is excited about the <a target="_blank" href="https://www.openapis.org/blog/2023/12/06/openapi-moonwalk-2024">plan to publish Moonwalk (OAS 4.0) in 2024</a>, but that's only half of the picture. I am (along with others) advocating for putting a lot of work into the 3.x line, including 3.0.y and 3.1.y patch releases, and a series of small, incremental 3.x releases starting with 3.2.</p>
<p>OpenAPI has developed a reputation for releasing giant changes every three to four years (3.1 qualifies despite being <a target="_blank" href="https://www.openapis.org/blog/2020/06/18/openapi-3-1-0-rc0-its-here">sincerely intended</a> as "minor"). These then take another three to four years to be broadly implemented and adopted. It's produced a bit of understandable grumbling mixed in with the Moonwalk excitement among folks who are just getting to 3.1, or are still on 3.0.</p>
<p>We're hoping to provide a smoother path of increased functionality this time, and we're just getting started <a target="_blank" href="https://github.com/OAI/OpenAPI-Specification/issues/3516">reviving and updating our processes</a> for easier participation while we produce multiple releases. I'm excited to figure out what pace of change will work best for the OpenAPI community.</p>
<h2 id="heading-oascomply">OASComply</h2>
<p>Much of my focus last year was on an <a target="_blank" href="https://learn.openapis.org/specification/structure.html">OpenAPI Description (OAD)</a> parser intended to accomplish several things:</p>
<ul>
<li><p>Illustrate how the OpenAPI Initiative interprets the OpenAPI Specification's (OAS) parsing requirements</p>
</li>
<li><p>Define a format for the parsed representation that can be used to test parsing compliance</p>
</li>
<li><p>Serve as the basis for further work, such as linting, a formal compliance test suite, or possibly automated upgrading from 3.x to Moonwalk</p>
</li>
</ul>
<p>Part of the way through the year we discovered ambiguities in the referencing requirements, so coding work is on hold while we resolve that (which will show up in the release planning somehow). But we expect to deliver a working tool this year.</p>
<h1 id="heading-json-schema-implementation">JSON Schema Implementation</h1>
<p>The OASComply work includes parsing both standard (but extended) JSON Schema (for OAS 3.1) and the "superset-subset" custom JSON Schema variation found in OAS 3.0. As I worked with a JSON Schema implementation to extend its capabilities, the owner eventually recommended that I make an authorized fork as the work needed to fully support OAS + JSON Schema is pretty extensive. I'll post more about this when I'm ready to release the first public version of the fork.</p>
<h1 id="heading-its-looking-like-a-busy-2024">It's looking like a busy 2024!</h1>
<p>As you can see, I'm doing a lot of both specification and coding work this year. One downside of specification work is you're often focused on things that won't reach your average end-user for 5+ years. I am hopeful we'll settle on an OpenAPI release approach that gets new features into the hands of end-users very quickly. I'm looking forward to writing more about that process as well as my tool development work in the very near future!</p>
]]></content:encoded></item><item><title><![CDATA[JSON Schema is a constraint system]]></title><description><![CDATA[Did you come to JSON Schema with an object-oriented programming (OOP) background? Do think of writing a schema as analogous to writing a class? These expectations are both common and understandable, but incorrect.
In this article, you'll learn:

What...]]></description><link>https://modern-json-schema.com/json-schema-is-a-constraint-system</link><guid isPermaLink="true">https://modern-json-schema.com/json-schema-is-a-constraint-system</guid><category><![CDATA[json-schema]]></category><category><![CDATA[json]]></category><category><![CDATA[Java]]></category><category><![CDATA[Object Oriented Programming]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Henry Andrews]]></dc:creator><pubDate>Fri, 11 Nov 2022 21:50:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1668195403111/YboqdcprM.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Did you come to JSON Schema with an object-oriented programming (OOP) background? Do think of writing a schema as analogous to writing a class? These expectations are both common and understandable, but incorrect.</p>
<p>In this article, you'll learn:</p>
<ul>
<li><p>What it means for JSON Schema to be a constraint system</p>
</li>
<li><p>How to think about designing constraints effectively</p>
</li>
<li><p>Why "constraint" encompasses more than just JSON Schema assertions</p>
</li>
</ul>
<h1 id="heading-constraints-vs-definitions">Constraints vs Definitions</h1>
<p>This is an empty schema (in all versions<a class="post-section-overview" href="#ft1"><sup>1</sup></a> of JSON Schema):</p>
<pre><code class="lang-JSON">{}
</code></pre>
<p>It <em>allows everything</em>.</p>
<p>This is an empty class in Java:</p>
<pre><code class="lang-Java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Empty</span> </span>{
}
</code></pre>
<p>It <em>does nothing</em>.</p>
<p>Building Java classes and JSON Schemas for a data model work from <em>opposite starting points</em> and require different approaches:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668195588042/Kn6ZD4UiV.png" alt="Empty Java class on left, empty schema on right, structured data model in the middle, with &quot;define&quot; left to center arrow and &quot;exclude&quot; right to center arrow as described in following paragraph" /></p>
<p>Class definition systems are <em>additive</em>: You start from nothing and the more you specify, the more you can do. On the left, our empty Java class is a black disc with no other colors. You add fields to <em>define</em> the correct set of possible data.</p>
<p>Constraint systems are <em>subtractive</em>: You start with everything and the more you specify, the less you can do. On the right, our empty JSON Schema is a black disc covered by a chaotic riot of color blobs. You add keywords to <em>exclude</em> all incorrect data. This thought process runs in the opposite direction compared to defining a class in Java.</p>
<p>Both processes converge in the middle, where our correct data model is shown as three colors at the points of an equilateral triangle on a black disc. So let's look at how these different processes work.</p>
<h2 id="heading-be-forbidding">Be forbidding!</h2>
<p>If we were thinking about Java classes and JSON Schemas in parallel, our next step might be adding a property to each (using a single public boolean data attribute for simplicity — colors and shapes just made a better visual!)</p>
<pre><code class="lang-Java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Empty</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> isOn;
}
</code></pre>
<pre><code class="lang-JSON">{
    <span class="hljs-attr">"properties"</span>: {
        <span class="hljs-attr">"isOn"</span>: {
            <span class="hljs-attr">"type"</span>: <span class="hljs-string">"boolean"</span>
        }
    }
}
</code></pre>
<p>While these <em>look</em> analogous, they are very different. Constraints in JSON Schema constrain as little as possible. This maximizes flexibility for schema authors. All this schema says is "<strong><em>if</em></strong> the instance is an object, and <strong><em>if</em></strong> it has a property named <code>isOn</code>, <strong><em>then</em></strong> that property must be a boolean."</p>
<p>In contrast, Java classes are inherently objects with named fields. Java classes <em>only</em> have the fields you declare. They <em>always</em> have those fields, even if you don't use them. The fields are initialized automatically, which for booleans means being set to <code>false</code>.</p>
<p>That's four additional constraints that we need to add to our JSON Schema (using JavaScript comment syntax):</p>
<pre><code class="lang-JSON">{
   <span class="hljs-attr">"type"</span>: <span class="hljs-string">"object"</span>,               <span class="hljs-comment">// forbid non-objects</span>
   <span class="hljs-attr">"required"</span>: [<span class="hljs-string">"isOn"</span>],           <span class="hljs-comment">// forbid objects without "isOn"</span>
   <span class="hljs-attr">"properties"</span>: {
       <span class="hljs-attr">"isOn"</span>: {
           <span class="hljs-attr">"type"</span>: <span class="hljs-string">"boolean"</span>,      <span class="hljs-comment">// forbid non-boolean "isOn"</span>
           <span class="hljs-attr">"default"</span>: <span class="hljs-literal">false</span>        <span class="hljs-comment">// forbid assuming "isOn" is true</span>
       }     
   },    
   <span class="hljs-attr">"additionalProperties"</span>: <span class="hljs-literal">false</span>   <span class="hljs-comment">// forbid props that aren't "isOn"</span>
}
</code></pre>
<p>This might seem strange. Why would you want to consider a non-object valid if you are describing object properties?</p>
<p>When you're writing a Java class, you are starting with Java's inherent concept of a class, with all of its automatic behaviors (such as attribute initialization) and assumptions (classes always having exactly the set of attributes that were declared, no more, no less). Java knows that you only want the things you say you want.</p>
<p>On the other hand, JSON Schema has <em>no idea what you're trying to do</em> and can't make any assumptions for you. It doesn't know that you're trying to match an OOP language. Even if it did, you could be writing in Perl, where a reference to <a target="_blank" href="https://perldoc.perl.org/perlobj#An-Object-is-Simply-a-Data-Structure"><em>anything</em></a>, even a number or string, can be "blessed" as a class instance and properties can be added or removed at any time.</p>
<p>This is why JSON Schema is a constraint system, and why you want to understand that instead of trying to use as if it were something else.<a class="post-section-overview" href="#ft2"><sup>2</sup></a> It has to work with anything that might be done in JSON, and it relies on <em>you</em> to ask yourself, <em>"have I</em> <strong><em>forbidden</em></strong> <em>everything I</em> <strong><em>don't</em></strong> <em>want?"</em></p>
<h2 id="heading-constraints-vs-validation-assertions">Constraints vs validation assertions</h2>
<p>JSON Schema has different keyword behaviors including <a target="_blank" href="https://www.ietf.org/archive/id/draft-bhutton-json-schema-01.html#name-assertions">assertions</a>, which can cause validation to fail, and <a target="_blank" href="https://www.ietf.org/archive/id/draft-bhutton-json-schema-01.html#name-annotations">annotations</a>, which can't fail validation but do provide additional information about valid instances.</p>
<p>All of the JSON Schema keywords in the example above are assertions <em>except</em> <code>"default"</code>, which is an annotation. But if you're using this schema for code generation, <code>"default"</code> is a constraint in that context. A <code>"default"</code> of <code>true</code> would require a generated Java class to initialize <code>isOn</code> to <code>true</code>. Non-assertions can be constraints in non-validation use cases!</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>In this article, you've learned that:</p>
<ul>
<li><p>JSON Schema is a constraint system because it can't know how you will use it</p>
</li>
<li><p>Java and similar languages know how you will use them, and make assumptions accordingly</p>
</li>
<li><p>The empty JSON Schema allows everything</p>
</li>
<li><p>The schema design mindset is: <em>"Have I forbidden everything I don't want?"</em></p>
</li>
<li><p>Whether a keyword functions as a constraint depends on how you are using the schema</p>
</li>
</ul>
<p>Please let me know what you think in the comments, and please click the "Follow" button so you don't miss the next two posts: First, an explanation of dynamic scopes, which you'll want to understand so you get the most out of the following post: When to use <code>"additionalProperties"</code> vs <code>"unevaluatedProperties"</code>!</p>
<hr />
<ol>
<li><p>In real-world usage, you should always specify <code>"$schema"</code>, as different implementations handle its absence differently. Some assume a default version (which might not be the one you expected), and others won't process such schemas at all because they don't want to risk giving an incorrect validation outcome with an inaccurate default assumption. To keep examples more readable, I'll often omit <code>"$schema"</code> when it doesn't change how the example is understood. <a class="post-section-overview" href="#1">↩</a></p>
</li>
<li><p>There have been some misguided attempts to reconcile OOP and constraints. For example, recent versions of the popular AJV implementation of JSON Schema set a bunch of <a target="_blank" href="https://ajv.js.org/strict-mode.html">"strict mode" options</a> by default. Many of these attempt to make JSON Schema behave more like a data definition system, but the resulting behavior is not compliant with the JSON Schema specification. In a future article, we'll look at when it is useful to use AJV's strict mode, and when it is problematic. While AJV's strict mode prevents certain valid schemas from being used rather than changing their outcome, this breaks interoperability as many things it prevents have valid use cases. Such schemas written for use with compliant implementations will fail with AJV, which is why the JSON Schema <a target="_blank" href="https://json-schema.org/implementations.html">implementations page</a> now notes implementations with noncompliant default behavior. <a class="post-section-overview" href="#2">↩</a></p>
</li>
</ol>
<hr />
]]></content:encoded></item><item><title><![CDATA[What is "Modern" JSON Schema?]]></title><description><![CDATA[Welcome to the Modern JSON Schema (& APIs) blog!  My name is Henry, and I'm the H. Andrews who co-authored all drafts of JSON Schema from 2017 to the present.  With this blog, I want to help you use JSON Schema to the full extent of its capabilities!...]]></description><link>https://modern-json-schema.com/what-is-modern-json-schema</link><guid isPermaLink="true">https://modern-json-schema.com/what-is-modern-json-schema</guid><category><![CDATA[json]]></category><category><![CDATA[json-schema]]></category><category><![CDATA[OpenApi]]></category><category><![CDATA[APIs]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Henry Andrews]]></dc:creator><pubDate>Thu, 10 Nov 2022 00:20:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1668039859082/HpRFnohhN.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome to the Modern JSON Schema (&amp; APIs) blog!  My name is Henry, and I'm the <em>H. Andrews</em> who co-authored all drafts of JSON Schema from 2017 to the present.  With this blog, I want to help <strong><em>you</em></strong> use JSON Schema to the full extent of its capabilities!</p>
<p>I'm excited to show you how "modern" JSON Schema, meaning 2019-09, <a target="_blank" href="https://www.ietf.org/archive/id/draft-bhutton-json-schema-01.html">2020-12</a>, and later, can solve far more problems than "classical" JSON Schema (draft-07 and earlier).  We'll also explore topics relevant to APIs in general and OpenAPI 3.1 in particular, and to all versions of JSON Schema.  If you're using classical JSON Schema, earlier versions of OpenAPI, or other approaches to HTTP APIs, you'll find plenty to interest you here as well.</p>
<p>In this introductory post, you'll learn:</p>
<ul>
<li>Why I'm making a distinction between "modern JSON Schema" and "classical JSON Schema"</li>
<li>Three areas of new functionality that modern JSON Schema has introduced</li>
</ul>
<h2 id="heading-why-modern-vs-classical-json-schema">Why "modern" vs "classical" JSON Schema?</h2>
<p>The JSON Schema landscape is pretty confusing right now.  There are five versions in active use: draft-04, draft-06, draft-07, and drafts<sup id="1"><a class="post-section-overview" href="#ft1">1</a></sup> 2019-09 and 2020-12.  When you get into the complexities of <a target="_blank" href="https://json-schema.org/specification-links.html#understanding-draft-names-and-numbers">IETF draft names vs meta-schema identifiers</a>, it all becomes excessively complicated:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668016208174/rbimY54B4.png" alt="A complex timeline of JSON Schema drafts with IETF and meta-schema identifiers grouped into three eras: &quot;pre-historic&quot; (2009-2012), &quot;classical&quot; (2013-2018), and &quot;modern&quot; (2019 onwards) as a simpler classification" /></p>
<p>Talking about all of these versions is confusing.  Talking about <em>eras</em>, only two of which are in use, is much simpler!</p>
<p>Simplifying the conversation is important, but there's a bit more to the name.  "Modern JSON Schema" is inspired by the successful branding of C++11 and later as <a target="_blank" href="https://github.com/isocpp/CppCoreGuidelines#background-and-scope">"modern C++"</a>.  C++11 made a <a target="_blank" href="https://en.wikipedia.org/wiki/C%2B%2B11#Extensions_to_the_C++_core_language">long list of changes</a> to the core language, just as JSON Schema 2019-09 significantly expanded JSON Schema's capabilities.  "Modern C++" is used in discussions and job descriptions to help people understand it as a distinct and desirable skill compared to C++03 and earlier.</p>
<p>I want to see a similar shift happen with JSON Schema.  We can build excitement around "modern JSON Schema" much more easily than around a pile of draft names and numbers.  We can focus on what unifies recent versions and sets them apart from the past.  We can create a healthy ecosystem where modern JSON Schema is in demand, but only if enough people understand why they should demand it and support it.</p>
<p>My hope for this blog is that it will further the community's understanding and generate that demand.</p>
<h2 id="heading-shiny-modern-things">Shiny modern things!</h2>
<p>So let's explore what makes modern JSON Schema, "modern"!  These three changes aren't the only changes between classical and modern JSON Schema, but they each dramatically expand what JSON Schema can do.</p>
<h3 id="heading-runtime-keyword-communication">Runtime keyword communication</h3>
<p>This change is about making schemas more re-usable.  How many of you tried to write a schema like this at some point?</p>
<pre><code class="lang-JSON">{
  <span class="hljs-attr">"$schema"</span>: <span class="hljs-string">"https://json-schema.org/draft-07/schema"</span>,
  <span class="hljs-attr">"type"</span>: <span class="hljs-string">"object"</span>,
  <span class="hljs-attr">"allOf"</span>: [{<span class="hljs-attr">"$ref"</span>: <span class="hljs-string">"https://example.com/schemas/sharedproperties"</span>}],
  <span class="hljs-attr">"additionalProperties"</span>: <span class="hljs-literal">false</span>
}
</code></pre>
<p>I did!  But any <a target="_blank" href="https://www.ietf.org/archive/id/draft-bhutton-json-schema-01.html#name-instance">instance</a> that has any properties will fail validation against this schema.  The <code>"additionalProperties"</code> keyword can't see into the <code>https://example.com/schemas/sharedproperties</code> schema, so it doesn't matter what it contains.</p>
<p>Modern JSON Schema allows keywords to record their runtime behavior for other keywords to read. 
 This allows keywords to build on the results of other keywords in ways that classical JSON Schema does not allow, such as by taking into account which properties that were validated in a referenced schema.</p>
<p>In future posts, we'll use a series of examples to look at how this works, and what advantages and drawbacks it brings.  You'll learn how modern JSON Schema makes it easy to solve several important use cases that used to be difficult or impossible.</p>
<h3 id="heading-annotations-for-application-aware-behavior">Annotations for application-aware behavior</h3>
<p>Even though JSON Schema has standard <code>"readOnly"</code> and <code>"writeOnly"</code> annotation keywords, it is challenging to use them to validate API request and response bodies if you're using classical JSON Schema.</p>
<p>JSON Schema validates the <em>structure</em> of the JSON data.  In the process of doing that it learns which fields are annotated with information such as <code>"readOnly": true</code>.  But it doesn't understand whether it's running on a client or a server, nor does it know the request and response semantics of different HTTP methods.  OpenAPI HTTP tooling understands these things, but it doesn't know which fields in the structure are read-only.  If these two systems could collaborate, they could validate the <em>usage</em> of the JSON data in the context of HTTP by extending standard JSON Schema tools.</p>
<p>Classical JSON Schema never defined what information made up an annotation, or how to report that information to applications such as OpenAPI tools.  Modern JSON Schema defines five pieces of information that make up an annotation, along with machine-readable formats for reporting it.  This allows OpenAPI tools to collaborate with standard JSON Schema implementations:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667976824568/tkzkJvJJK.png" alt="left to right: JSON Schema validation (valid) and annotation (/user/id is readOnly, /user/password is writeOnly), then OpenAPI HTTP usage (PUT request on server, /user/id unchanged therefore valid, /user/password changeable therefore valid)" /></p>
<p>Here we see JSON Schema validating a PUT request payload on the server, and reporting one read-only and one write-only field as annotations.  For the purpose of this example, read-only fields can be present as long as they don't change the field's value.  The OpenAPI tool checks that the read-only field is unchanged, and knows that the write-only field is allowed because a PUT request is a write.</p>
<p>This shows how modern JSON Schema annotations enable standardized collaboration among tools that was not previously possible!  We'll explore the five parts of an annotation along with many scenarios where applications can leverage JSON Schema annotations to perform a wide variety of tasks.</p>
<h3 id="heading-vocabularies-you-yes-you-can-extend-json-schema">Vocabularies: You (yes, you!) can extend JSON Schema</h3>
<p>Vocabularies allow anyone to define JSON Schema keywords that can be used reliably with any compliant implementations.  Classical JSON Schema allows extension keywords, but you can't guarantee that they'll be respected.  Unrecognized extension keywords are silently ignored, which results in invalid data being declared valid.</p>
<p>Modern JSON Schema introduces vocabularies, which allow you to define a group of keywords and identify them with a URI.  Schema authors can then use that URI to tell implementations that the need to support the vocabulary in order to use the schema.  If they can't, instead of failing validation, the implementation refuses to run the schema and indicates which vocabularies it doesn't understand.</p>
<p>This is just like finding out that you need to install a 3rd-party library to run a piece of software.  Hopefully it will one day be easy to find vocabulary plugins when you need them.  But even if you can't find support for a vocabulary, it's much better for an implementation to refuse to use the schema than it is to incorrectly claim that the data is valid!  Getting the right error is the first step to fixing it.</p>
<p>We'll spend a whole series of posts understanding <em>why</em> you should care about vocabularies and what you need to know about them.  We'll walk through examples of how to design and implement them, paying special attention to vocabularies that can be created and used <em>without</em> having to write custom code.  This is an area that is still evolving, and I hope this blog will start conversations that help us finalize vocabularies in a way that makes them accessible to everyone who wants create keywords.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, you've learned that:</p>
<ul>
<li>"Modern JSON Schema" is a way to simplify how we talk about JSON Schema and promote the expanded capabilities of its recent versions</li>
<li>Runtime keyword communication makes modern JSON Schema more re-usable</li>
<li>Modern JSON Schema's annotations and output formats allow applications to build on JSON Schema in a standardized way</li>
<li>Vocabularies allow anyone to create new keywords and ensure that they will be used correctly rather than being silently ignored</li>
</ul>
<p>Thank you for reading this introductory post!  Future posts will go deeper into these and other topics, including detailed examples.  My goal is to keep posts short (less than 1000 words) and frequent, with the occasional longer deep dive.</p>
<p><strong>In the next post</strong> we'll examine how the mental model for working with JSON Schema differs from working with object-oriented programming.  Understanding this is fundamental to really getting comfortable with how JSON Schema works.  Please click the "+Follow" button at the top of the page as you will not want to miss it!</p>
<p>I am very excited to be writing this blog, and have several articles near completion that you can expect to see within the next week.  There is so much to say about JSON Schema and APIs, and I would love to hear what topics would interest you!  Please let me know in the comments! 👇</p>
<hr />
<ol>
<li><span id="ft1"></span> The "draft" label is by now mostly due to historical inertia, and <a target="_blank" href="https://json-schema.org/blog/posts/future-of-json-schema">will be dropped soon</a> in favor of a release model with better compatibility guarantees.  For modern JSON Schema I generally won't bother with the "draft" label.  2020-12 in particular is the base from which our new push towards stability will start. <a class="post-section-overview" href="#1">↩</a></li>
</ol>
<hr />
]]></content:encoded></item></channel></rss>