feat: add JSON Schema export functionality - #532
Conversation
Add comprehensive JSON Schema export capability to voluptuous schemas, addressing issue alecthomas#408. This enables integration with modern IDEs, API documentation tools, and other validation systems. Features: - Convert voluptuous schemas to JSON Schema format - Support for all major validators (Range, Length, Email, URL, etc.) - Handle composite validators (All, Any, ExactSequence) - Proper Required/Optional marker conversion - Nested object and array schema support - Default value handling with JSON serialization safety API: - Schema.to_json_schema() method on Schema instances - to_json_schema() standalone function - Full backward compatibility maintained Testing: - Comprehensive test suite with 100% coverage - Real-world example scenarios - Edge case handling - JSON serialization validation Documentation: - Updated README with usage examples - Complete example script demonstrating features - Inline documentation and docstrings Closes alecthomas#408
- Replace bare except clause with specific exception types - Fix all 17 mypy type checking errors: * Add proper type annotations for Dict[str, Any] * Replace callable with typing.Callable * Fix incompatible type assignments * Resolve indexing operation type issues * Add type safety for validator method parameters - Remove unused import (voluptuous.validators) - Maintain full backward compatibility and functionality All flake8 and mypy checks now pass with zero issues. All 162 existing tests continue to pass.
efd7df1 to
d8092eb
Compare
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d8092eb81d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| """ | ||
| json_schema: Dict[str, Any] = { | ||
| "$schema": "https://json-schema.org/draft/2020-12/schema", | ||
| "type": "object", |
There was a problem hiding this comment.
Remove the unconditional object type from root schemas
When the root conversion does not itself contain a type—for example Schema('x'), Schema(In(['x', 'y'])), Schema(Any(str, int)), or Schema(All(str, Length(min=2)))—the later update() retains this initial "type": "object". The exported schema therefore rejects every value accepted by these root schemas because a value cannot simultaneously be an object and the declared scalar alternative or constant.
Useful? React with 👍 / 👎.
| # Multiple different schemas - use prefixItems for ordered validation | ||
| return { | ||
| "type": "array", | ||
| "prefixItems": items_schemas, | ||
| "items": False, # No additional items allowed |
There was a problem hiding this comment.
Export heterogeneous sequence schemas as item alternatives
For schemas such as Schema([str, int]), Voluptuous tries every listed validator for every element and permits arbitrary length and order, but this branch emits an ordered two-element tuple schema with no additional items. Consequently valid inputs such as [1, 'x'] or ['x', 'y', 'z'] are rejected by the exported schema; items: {"anyOf": ...} is needed here, while ordered behavior belongs to ExactSequence.
Useful? React with 👍 / 👎.
| # Regular key | ||
| prop_name = str(key) | ||
| json_schema["properties"][prop_name] = self._convert_schema_element( | ||
| value |
There was a problem hiding this comment.
Preserve validator-based mapping keys
When a mapping uses a key validator, such as the documented feature-flag pattern {str: bool}, converting the validator to the literal property name "<class 'str'>" while disabling additional properties rejects every normal key such as "feature_a". Voluptuous applies these keys dynamically, so the export must represent their key/value constraints with patternProperties, propertyNames, or an appropriate additionalProperties schema rather than stringify the validator.
Useful? React with 👍 / 👎.
| json_schema: Dict[str, Any] = { | ||
| "type": "object", | ||
| "properties": {}, | ||
| "additionalProperties": False, | ||
| } |
There was a problem hiding this comment.
Honor the Schema extra-key policy
The object conversion always starts with additionalProperties: false and never reads Schema.extra. Thus Schema({'x': str}, extra=ALLOW_EXTRA) accepts {'x': 'a', 'y': 1} in Voluptuous but its exported schema rejects it; REMOVE_EXTRA inputs are similarly accepted before transformation. The generated additional-properties behavior should be derived from the applicable Schema instance.
Useful? React with 👍 / 👎.
| for key, value in mapping.items(): | ||
| if key is Extra: | ||
| json_schema["additionalProperties"] = True | ||
| continue |
There was a problem hiding this comment.
Retain the value constraint attached to Extra
For an explicit schema such as {Extra: int}, Voluptuous allows arbitrary keys only when their values are integers, but this branch emits plain additionalProperties: true and discards the associated value schema. The exported schema therefore accepts invalid values such as {'x': 'not-an-int'}; additionalProperties should contain the converted value schema.
Useful? React with 👍 / 👎.
| if hasattr(length_validator, 'min') and length_validator.min is not None: | ||
| schema["minLength"] = length_validator.min | ||
|
|
||
| if hasattr(length_validator, 'max') and length_validator.max is not None: | ||
| schema["maxLength"] = length_validator.max |
There was a problem hiding this comment.
Emit array length keywords for array validators
When Length is combined with an array schema, for example All([int], Length(min=2, max=3)), this converter emits minLength and maxLength. Those keywords apply only to strings and are ignored for arrays, so the exported schema accepts arrays of any size even though Voluptuous rejects them; the surrounding validated type must determine whether to emit minItems/maxItems (or minProperties/maxProperties) instead.
Useful? React with 👍 / 👎.
Add comprehensive JSON Schema export capability to voluptuous schemas, addressing issue #408. This enables integration with modern IDEs, API documentation tools, and other validation systems.
Features:
API:
Testing:
Documentation:
Closes #408