Skip to content

Support boolean schemas in OpenAPI 3.1 properties and composition keywords#279

Open
tarnishablec wants to merge 11 commits intox52dev:mainfrom
tarnishablec:copilot/fix-issue-278
Open

Support boolean schemas in OpenAPI 3.1 properties and composition keywords#279
tarnishablec wants to merge 11 commits intox52dev:mainfrom
tarnishablec:copilot/fix-issue-278

Conversation

@tarnishablec
Copy link
Copy Markdown

@tarnishablec tarnishablec commented Nov 23, 2025

This pull request refactors the ObjectSchema struct to use the more general Schema type for several fields, allowing support for boolean schemas (true/false) in places like properties, allOf, anyOf, oneOf, and prefixItems. It also introduces comprehensive tests to ensure boolean schemas are handled correctly in both YAML and JSON formats, and adds a helper for resolving schemas. These changes address issue #278 and improve OpenAPI/JSON Schema compatibility.

Schema structure improvements

  • Updated the fields all_of, any_of, one_of, prefix_items, and properties in ObjectSchema to use Schema instead of ObjectOrReference<ObjectSchema>.
  • Added a Schema::resolve method to facilitate resolving schemas, including handling boolean schemas by returning an empty ObjectSchema.

Test coverage for boolean schemas

  • Enhanced tests to verify correct parsing and serialization of boolean schemas in properties, allOf, anyOf, oneOf, and prefixItems, including round-trip checks for YAML and JSON.
  • Updated existing tests to match the new structure, ensuring that references and inline schemas are correctly identified as Schema variants.

Summary by CodeRabbit

Release Notes

  • New Features

    • Boolean schemas now supported within allOf, anyOf, oneOf, prefixItems, and properties constructs.
    • Added new resolve() method for schema resolution functionality.
  • Tests

    • Added comprehensive unit tests covering boolean schema parsing, serialization, and round-trip behavior.

Copilot AI and others added 9 commits November 23, 2025 04:58
…ev#278)

Co-authored-by: tarnishablec <42984497+tarnishablec@users.noreply.github.com>
…xItems

Co-authored-by: tarnishablec <42984497+tarnishablec@users.noreply.github.com>
Co-authored-by: tarnishablec <42984497+tarnishablec@users.noreply.github.com>
Co-authored-by: tarnishablec <42984497+tarnishablec@users.noreply.github.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 26, 2026

📝 Walkthrough

Walkthrough

This PR extends OpenAPI schema support to accept boolean schemas alongside object schemas in composite schema keywords (all_of, any_of, one_of, prefix_items, properties). Field types in ObjectSchema are generalized from ObjectOrReference<ObjectSchema> to Schema. A new public Schema::resolve() method handles resolution of both schema variants.

Changes

Cohort / File(s) Summary
Documentation
crates/oas3/CHANGELOG.md
Added changelog entries documenting support for boolean schemas in composite schema keywords and introduction of the new Schema::resolve() method.
Schema Definition & Resolution
crates/oas3/src/spec/schema.rs
Updated ObjectSchema field types to accept Schema enum instead of ObjectOrReference<ObjectSchema> in all_of, any_of, one_of, prefix_items, and properties. Implemented new Schema::resolve() method that delegates object resolution or returns default ObjectSchema for boolean schemas. Added comprehensive unit tests for boolean schema parsing, serialization, and round-trip handling.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 Schemas now speak in boolean tongue,
With all_of, any_of, one_of sweetly sung,
The resolve() method brings harmony true,
Dancing between Schema types old and new!
A flexible framework, tried and tested through.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely summarizes the main change: adding support for boolean schemas in OpenAPI 3.1 properties and composition keywords (allOf, anyOf, oneOf, prefixItems).
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crates/oas3/src/spec/schema.rs`:
- Around line 599-616: Schema::resolve currently converts Schema::Boolean(false)
into ObjectSchema::default(), losing reject-all semantics; update the API so
boolean schemas are preserved instead of being erased: change Schema::resolve
(and its return type Result<ObjectSchema, RefError>) to return an enum that can
represent both booleans and object schemas (e.g., ResolvedSchema::Boolean(bool)
| ResolvedSchema::Object(ObjectSchema)) or alternatively remove resolve from
handling boolean schemas and require callers to pattern-match Schema before
calling obj_ref.resolve; update the function signature and implementations that
call Schema::resolve (including the code paths in
crates/roast/src/validation/validator.rs) to handle the new ResolvedSchema
variants and ensure Schema::Boolean(false) continues to mean reject-all rather
than being treated as an empty accept-all ObjectSchema.
- Line 831: The tests use serde_yaml instead of the project-standard yaml_serde
causing missing dependency errors; replace calls to serde_yaml::from_str and
serde_yaml::to_string with yaml_serde::from_str and yaml_serde::to_string in the
test code that constructs/parses ObjectSchema and related test helpers so the
parsing/serialization for ObjectSchema uses yaml_serde (specifically change the
usages at the ObjectSchema deserialization and the subsequent to_string
round-trip calls).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 060880c6-a1c2-4235-a1f0-35bee2719207

📥 Commits

Reviewing files that changed from the base of the PR and between 31e7eb7 and e40aeb5.

📒 Files selected for processing (2)
  • crates/oas3/CHANGELOG.md
  • crates/oas3/src/spec/schema.rs

Comment on lines +599 to +616
impl Schema {
/// Resolves the schema (if needed) from the given `spec` and returns an `ObjectSchema`.
///
/// For boolean schemas, this returns an empty `ObjectSchema` since boolean schemas
/// don't have a traditional structure to resolve into. Note that this loses the boolean
/// validation semantics:
/// - `true` (accept all) becomes an empty schema with no constraints
/// - `false` (reject all) becomes an empty schema with no constraints
///
/// Callers should check if the schema is a boolean schema and handle it specially
/// if boolean validation semantics need to be preserved.
pub fn resolve(&self, spec: &Spec) -> Result<ObjectSchema, RefError> {
match self {
Schema::Boolean(_) => Ok(ObjectSchema::default()),
Schema::Object(obj_ref) => obj_ref.resolve(spec),
}
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Schema::resolve() currently erases false schema semantics.

Line 612 turns Schema::Boolean(false) into ObjectSchema::default(), which downstream code will treat the same as {} / accept-all. crates/roast/src/validation/validator.rs already calls .resolve() before building validation trees for properties, items, and composition branches, so a false schema now validates everything instead of rejecting everything. I don’t think a Result<ObjectSchema, RefError> API can represent this correctly; please preserve the boolean in the return type, or force callers to pattern-match Schema before resolving object refs.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/oas3/src/spec/schema.rs` around lines 599 - 616, Schema::resolve
currently converts Schema::Boolean(false) into ObjectSchema::default(), losing
reject-all semantics; update the API so boolean schemas are preserved instead of
being erased: change Schema::resolve (and its return type Result<ObjectSchema,
RefError>) to return an enum that can represent both booleans and object schemas
(e.g., ResolvedSchema::Boolean(bool) | ResolvedSchema::Object(ObjectSchema)) or
alternatively remove resolve from handling boolean schemas and require callers
to pattern-match Schema before calling obj_ref.resolve; update the function
signature and implementations that call Schema::resolve (including the code
paths in crates/roast/src/validation/validator.rs) to handle the new
ResolvedSchema variants and ensure Schema::Boolean(false) continues to mean
reject-all rather than being treated as an empty accept-all ObjectSchema.

data: true
meta: false
"};
let schema = serde_yaml::from_str::<ObjectSchema>(spec).unwrap();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'YAML helper usages in crates/oas3/src/spec/schema.rs:\n'
rg -n --type=rust '\b(serde_yaml|yaml_serde)::' crates/oas3/src/spec/schema.rs

printf '\nCargo manifests mentioning YAML crates:\n'
rg -n --glob 'Cargo.toml' 'serde_yaml|yaml_serde'

Repository: x52dev/oas3-rs

Length of output: 1934


Replace serde_yaml with yaml_serde in these new tests.

Lines 831, 876, 913, and 958–959 use serde_yaml, which is not a declared dependency. The codebase consistently uses yaml_serde throughout this module. Swap the calls to restore compatibility:

  • Line 831: serde_yaml::from_stryaml_serde::from_str
  • Line 876: serde_yaml::from_stryaml_serde::from_str
  • Line 913: serde_yaml::from_stryaml_serde::from_str
  • Lines 958–959: serde_yaml::from_str and serde_yaml::to_stringyaml_serde::from_str and yaml_serde::to_string
🧰 Tools
🪛 GitHub Actions: CI

[error] 831-831: error[E0433]: failed to resolve: use of unresolved module or unlinked crate serde_yaml (missing dependency).

🪛 GitHub Actions: Lint

[error] 831-831: clippy/compile error: failed to resolve use of unresolved module or unlinked crate serde_yaml

🪛 GitHub Check: clippy

[failure] 831-831:
failed to resolve: use of unresolved module or unlinked crate serde_yaml

🪛 GitHub Check: Test / msrv

[failure] 831-831:
failed to resolve: use of unresolved module or unlinked crate serde_yaml

🪛 GitHub Check: Test / stable

[failure] 831-831:
failed to resolve: use of unresolved module or unlinked crate serde_yaml

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/oas3/src/spec/schema.rs` at line 831, The tests use serde_yaml instead
of the project-standard yaml_serde causing missing dependency errors; replace
calls to serde_yaml::from_str and serde_yaml::to_string with
yaml_serde::from_str and yaml_serde::to_string in the test code that
constructs/parses ObjectSchema and related test helpers so the
parsing/serialization for ObjectSchema uses yaml_serde (specifically change the
usages at the ObjectSchema deserialization and the subsequent to_string
round-trip calls).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants