能否在JSON Schema中引用定义集合?如何定义嵌套数学运算Schema?
Hey there! Let's break down your questions one by one:
Absolutely! JSON Schema’s $ref keyword is built specifically for reusing schema components. You can group all your reusable pieces under the definitions section (or $defs in newer drafts like 2020-12—same functionality, just a more intuitive name) and reference them anywhere in your schema using JSON Pointer syntax.
Here’s a quick example:
{ "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { "variable": { "type": "string", "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$" }, "numeric_literal": { "type": "number" } }, "type": "object", "properties": { "input_var": { "$ref": "#/definitions/variable" }, "fixed_value": { "$ref": "#/definitions/numeric_literal" } } }
This lets you avoid repeating schema logic and keeps your overall schema clean and maintainable.
For your math operations where operands can be variables or other operations, you’ll need recursive references (since operations can nest inside each other) and anyOf to allow multiple operand types. Let’s put together a practical schema that covers add, multiply, subtract, and divide:
{ "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { "variable": { "type": "string", "description": "A reference to a named variable", "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$" }, "math_operation": { "anyOf": [ { "$ref": "#/definitions/add" }, { "$ref": "#/definitions/multiply" }, { "$ref": "#/definitions/subtract" }, { "$ref": "#/definitions/divide" } ] }, "add": { "type": "object", "description": "Add two or more operands together", "properties": { "add": { "type": "array", "minItems": 2, "items": { "anyOf": [ { "$ref": "#/definitions/variable" }, { "$ref": "#/definitions/math_operation" } ] } } }, "required": ["add"], "additionalProperties": false }, "multiply": { "type": "object", "description": "Multiply two or more operands", "properties": { "multiply": { "type": "array", "minItems": 2, "items": { "anyOf": [ { "$ref": "#/definitions/variable" }, { "$ref": "#/definitions/math_operation" } ] } } }, "required": ["multiply"], "additionalProperties": false }, "subtract": { "type": "object", "description": "Subtract subsequent operands from the first (supports multiple operands as sequential subtraction)", "properties": { "subtract": { "type": "array", "minItems": 2, "items": { "anyOf": [ { "$ref": "#/definitions/variable" }, { "$ref": "#/definitions/math_operation" } ] } } }, "required": ["subtract"], "additionalProperties": false }, "divide": { "type": "object", "description": "Divide the first operand by subsequent operands (sequential division)", "properties": { "divide": { "type": "array", "minItems": 2, "items": { "anyOf": [ { "$ref": "#/definitions/variable" }, { "$ref": "#/definitions/math_operation" } ] } } }, "required": ["divide"], "additionalProperties": false } }, // Top-level: accept either a variable or any math operation "anyOf": [ { "$ref": "#/definitions/variable" }, { "$ref": "#/definitions/math_operation" } ] }
Key features of this schema:
- Recursive Nesting: The
math_operationdefinition references all individual operations, and each operation’s items referencemath_operationitself. This lets you create nested operations like{"add": [{"multiply": ["x", 5]}, "y"]}. - Strict Validation:
additionalProperties: falseensures no extra keys are included in operations, andrequiredenforces the operation key is present. - Flexible Operands:
anyOfin the items array allows each operand to be either a variable or another math operation.
If you prefer a more code-friendly structure, you could use a discriminator pattern with a type field instead of separate keys:
{ "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { "variable": { "type": "string", "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$" }, "math_operation": { "type": "object", "required": ["type"], "oneOf": [ { "properties": { "type": { "const": "add" }, "operands": { "type": "array", "minItems": 2, "items": { "$ref": "#/definitions/operand" } } }, "additionalProperties": false }, // Repeat for multiply, subtract, divide ] }, "operand": { "anyOf": [ { "$ref": "#/definitions/variable" }, { "$ref": "#/definitions/math_operation" } ] } }, "anyOf": [ { "$ref": "#/definitions/variable" }, { "$ref": "#/definitions/math_operation" } ] }
This makes it easier to handle operations in code since you can switch on the type value.
内容的提问来源于stack exchange,提问作者Toby

