Reading & Writing Documents
This page covers how to parse, create, serialize, and clone documents.
Reading a Document
The library auto-detects the specification type and version by examining top-level properties
like openapi, asyncapi, swagger, openrpc, and $schema.
readRoot and readRootFromJSONString return a RootCapable — the supertype of everything
that can sit at the root of a document. For OpenAPI, AsyncAPI and OpenRPC that is a Document;
for JSON Schema it is a schema, which is not a Document. A JSON Schema document may also be
the literal true or false: it is read as a BooleanUnionValue, which is a JsonSchema and a
RootCapable but not a Node, and written with writeRoot (see below). It carries no
$schema, so it is read as draft 7.
From a JSON String
From a Parsed JSON Object
If you already have a parsed JSON object, pass it directly.
Casting to a Specific Type
After reading, cast to the specific type for typed access to its properties.
A JSON Schema document is read the same way, but its root is a schema rather than a document:
The Document-typed read methods are deprecated
readDocument and readDocumentFromJSONString still work for OpenAPI, AsyncAPI and
OpenRPC, but throw UnsupportedModelTypeException for JSON Schema, whose root is not a
Document. Prefer readRoot / readRootFromJSONString, which work for every
specification. See the
migration guide.
Creating a New Document
Use Library.createRoot() with a ModelType to create a new, empty document. Then populate it
using typed setters and createXxx() factory methods.
import io.apitomy.datamodels.Library;
import io.apitomy.datamodels.models.ModelType;
import io.apitomy.datamodels.models.openapi.OpenApiPathItem;
import io.apitomy.datamodels.models.openapi.v3x.v30.OpenApi30Document;
OpenApi30Document doc = (OpenApi30Document) Library.createRoot(ModelType.OPENAPI30);
// Set the info section
doc.setInfo(doc.createInfo());
doc.getInfo().setTitle("Pet Store");
doc.getInfo().setVersion("1.0.0");
doc.getInfo().setDescription("A sample API for pets");
// Add a path
doc.setPaths(doc.createPaths());
doc.getPaths().addItem("/pets", doc.getPaths().createPathItem());
// Add a GET operation to the path
OpenApiPathItem pathItem = doc.getPaths().getItem("/pets");
pathItem.setGet(pathItem.createOperation());
pathItem.getGet().setOperationId("listPets");
pathItem.getGet().setSummary("List all pets");
import { Library, ModelType, OpenApi30Document } from '@apitomy/data-models';
const doc = Library.createRoot(ModelType.OPENAPI30) as OpenApi30Document;
// Set the info section
doc.setInfo(doc.createInfo());
doc.getInfo().setTitle('Pet Store');
doc.getInfo().setVersion('1.0.0');
doc.getInfo().setDescription('A sample API for pets');
// Add a path
doc.setPaths(doc.createPaths());
doc.getPaths().addItem('/pets', doc.getPaths().createPathItem());
// Add a GET operation to the path
const pathItem = doc.getPaths().getItem('/pets');
pathItem.setGet(pathItem.createOperation());
pathItem.getGet().setOperationId('listPets');
pathItem.getGet().setSummary('List all pets');
Note
createDocument is deprecated for the same reason as readDocument — it throws for JSON
Schema model types.
Available Model Types
| ModelType | Specification |
|---|---|
OPENAPI20 |
OpenAPI 2.0 (Swagger) |
OPENAPI30 |
OpenAPI 3.0.x |
OPENAPI31 |
OpenAPI 3.1.x |
OPENAPI32 |
OpenAPI 3.2.x |
ASYNCAPI20 – ASYNCAPI26 |
AsyncAPI 2.0 through 2.6 |
ASYNCAPI30, ASYNCAPI31 |
AsyncAPI 3.0, 3.1 |
OPENRPC13, OPENRPC14 |
OpenRPC 1.3, 1.4 |
JD4, JD6, JD7 |
JSON Schema Draft 4, 6, 7 |
JM201909, JM202012 |
JSON Schema 2019-09, 2020-12 |
JC |
JSON Schema compound (all drafts merged — see Schema Compatibility) |
Writing a Document
writeNode serializes any node, including a document or schema root. The one root it cannot
take is a boolean JSON Schema, which is not a node; writeRoot and writeRootToJSONString write
any root, as returned by readRoot, including that one.
To a JSON Object
To a JSON String
Writing a Single Node
The same method serializes any individual node in the tree, not just the root.
Note
writeDocument and writeDocumentToJSONString are deprecated. They accept only a
Document, so they cannot serialize a JSON Schema root. writeNode and writeNodeToString
replace them.
Cloning a Document
Create a deep copy. The clone is fully independent of the original.
cloneDocument takes a Document, so for a JSON Schema root use a ModelCloner, which clones
any node:
Error Handling
The library uses a typed exception hierarchy rooted at DataModelsException (which extends
RuntimeException for backward compatibility). When reading a document with an unrecognized
specification version, the library throws UnsupportedModelTypeException.
| Exception | Thrown When |
|---|---|
DataModelsException |
Base class for all library exceptions |
UnsupportedModelTypeException |
Unknown or unsupported specification version, or a deprecated Document-typed method called with a JSON Schema root |
TransformationException |
Unsupported document transformation (see Document Transformation) |
CommandException |
Command marshalling or unmarshalling failure (see Commands) |
Extra Properties
API specifications allow vendor extensions (properties prefixed with x-). These are
preserved as "extra properties" on each node.
import com.fasterxml.jackson.databind.node.TextNode;
// Add a custom extension
doc.getInfo().addExtraProperty("x-api-owner", new TextNode("platform-team"));
// Read it back
String owner = doc.getInfo().getExtraProperty("x-api-owner").asText();
// List all extensions on a node
List<String> extensions = doc.getInfo().getExtraPropertyNames();