Skip to main content

openapi_schema_to_json_schema/
lib.rs

1//! Convert OpenAPI 3.0 schema objects to JSON Schema draft-04.
2//!
3//! OpenAPI 3.0 describes schemas with an extended subset of JSON Schema that is
4//! not itself valid JSON Schema draft-04. This crate bridges the gap. It takes
5//! an OpenAPI 3.0 Schema Object as a [`serde_json::Value`] and returns a
6//! draft-04 document.
7//!
8//! The conversion is pure and in memory. It performs no I/O, no network access,
9//! and no `$ref` resolution. References pass through untouched, so resolve them
10//! before calling if you need them inlined.
11//!
12//! # What it does
13//!
14//! - `nullable: true` becomes `"null"` added to `type`, and `null` appended to
15//!   an `enum` when present.
16//! - OpenAPI-only keywords are stripped: `nullable`, `discriminator`,
17//!   `readOnly`, `writeOnly`, `xml`, `externalDocs`, `example`, `deprecated`.
18//! - Numeric formats (`int32`, `int64`, `float`, `double`) become
19//!   `minimum`/`maximum` bounds. `byte` becomes a base64 `pattern`. `date`
20//!   optionally becomes `date-time`.
21//! - Combiner and struct keywords recurse: `allOf`, `anyOf`, `oneOf`, `not`,
22//!   `items`, `additionalProperties`, and `properties`.
23//! - `required` drops names whose property was removed during conversion, and
24//!   keeps names that have no `properties` entry.
25//! - In strict mode, an invalid `type` raises an error.
26//!
27//! The root of the result carries `"$schema": "http://json-schema.org/draft-04/schema#"`.
28//! Nested schemas do not.
29//!
30//! # Example
31//!
32//! ```
33//! use openapi_schema_to_json_schema::{from_schema, Options};
34//! use serde_json::json;
35//!
36//! let input = json!({ "type": "string", "nullable": true });
37//! let output = from_schema(input, &Options::new()).unwrap();
38//! assert_eq!(
39//!     output,
40//!     json!({
41//!         "type": ["string", "null"],
42//!         "$schema": "http://json-schema.org/draft-04/schema#"
43//!     })
44//! );
45//! ```
46
47#![forbid(unsafe_code)]
48#![warn(missing_docs)]
49
50mod consts;
51mod error;
52mod options;
53mod parameter;
54mod pattern;
55mod schema;
56mod value;
57
58pub use error::Error;
59pub use options::{
60    AfterTransform, BeforeTransform, Options, PatternPropertiesHandler, ResolvedOptions,
61};
62
63use serde_json::Value;
64
65/// Convert an OpenAPI 3.0 Schema Object to a JSON Schema draft-04 document.
66///
67/// The root of the returned value carries `$schema`. The input is not mutated.
68/// The root must be an object or an array. An array passes through unchanged.
69///
70/// # Errors
71///
72/// Returns [`Error::InvalidType`] when strict mode is on and any node carries a
73/// `type` value outside the draft-04 type set. Returns [`Error::InvalidInput`]
74/// when the root is a scalar or null.
75///
76/// # Example
77///
78/// ```
79/// use openapi_schema_to_json_schema::{from_schema, Options};
80/// use serde_json::json;
81///
82/// let out = from_schema(json!({ "type": "integer", "format": "int32" }), &Options::new()).unwrap();
83/// assert_eq!(out["minimum"], json!(-2147483648_i64));
84/// assert_eq!(out["maximum"], json!(2147483647_i64));
85/// ```
86pub fn from_schema(schema: Value, options: &Options) -> Result<Value, Error> {
87    let resolved = options::resolve_options(options);
88    schema::convert_from_schema(schema, &resolved)
89}
90
91/// Convert an OpenAPI 3.0 Parameter Object or Response Object.
92///
93/// With a `schema` member the result is a single JSON Schema. With a `content`
94/// member the result is a map keyed by MIME type, where each value is a JSON
95/// Schema with its own `$schema`. The outer map has no `$schema`.
96///
97/// A truthy `description` on the parameter is copied onto each result.
98///
99/// # Errors
100///
101/// Returns [`Error::InvalidInput`] when strict mode is on and the parameter has
102/// neither a `schema` nor a `content` member. Returns [`Error::InvalidType`]
103/// under the same conditions as [`from_schema`].
104///
105/// # Example
106///
107/// ```
108/// use openapi_schema_to_json_schema::{from_parameter, Options};
109/// use serde_json::json;
110///
111/// let param = json!({
112///     "name": "id",
113///     "in": "query",
114///     "schema": { "type": "string", "nullable": true }
115/// });
116/// let out = from_parameter(param, &Options::new()).unwrap();
117/// assert_eq!(out["type"], json!(["string", "null"]));
118/// ```
119pub fn from_parameter(parameter: Value, options: &Options) -> Result<Value, Error> {
120    let resolved = options::resolve_options(options);
121    parameter::convert_from_parameter(parameter, &resolved)
122}