JSON Schema as an input
Processor Options
The JSON Schema input processor provides several options to customize how schemas are interpreted into models. These options can be passed to the generator via the processorOptions parameter.
Available Options
interpretSingleEnumAsConst
Type: boolean (default: false)
When enabled, a single enum value like {enum: ['test']} will be interpreted the same as {const: 'test'}. This reduces the number of enums being generated and uses constant values instead.
Example:
1const generator = new TypeScriptGenerator({ 2 processorOptions: { 3 jsonSchema: { 4 interpretSingleEnumAsConst: true 5 } 6 } 7});
See the json-schema-single-enum-as-const example for a complete usage example.
propertyNameForAdditionalProperties
Type: string (default: 'additionalProperties')
Changes which property name should be used to represent additionalProperties in JSON Schema. This is useful when you want to customize the generated property name for additional properties in your models.
Example:
1const generator = new TypeScriptGenerator({ 2 processorOptions: { 3 jsonSchema: { 4 propertyNameForAdditionalProperties: 'metadata' 5 } 6 } 7});
See the json-schema-additional-properties-representation example for a complete usage example.
allowInheritance
Type: boolean (default: false)
Enables support for inheritance in the generated models. When enabled, models can extend from other models based on the schema structure (such as allOf patterns).
Example:
1const generator = new TypeScriptGenerator({ 2 processorOptions: { 3 jsonSchema: { 4 allowInheritance: true 5 } 6 } 7});
See the json-schema-allow-inheritance example for a complete usage example.
disableCache
Type: boolean (default: false)
Disables the seenSchemas cache in the Interpreter. This option should only be used in specific internal scenarios and generally should not be modified by end users.
ignoreAdditionalProperties
Type: boolean (default: false)
For JSON Schema draft 7, additionalProperties are by default true, but this might create unintended properties in the models. Use this option to ignore default additionalProperties for models that have other properties defined with them.
Note: ONLY use this option if you do not have control over your schema files. Instead, adapt your schemas to be more strict by setting additionalProperties: false.
Example:
1const generator = new TypeScriptGenerator({ 2 processorOptions: { 3 jsonSchema: { 4 ignoreAdditionalProperties: true 5 } 6 } 7});
See the json-schema-ignore-additional-properties example for a complete usage example.
ignoreAdditionalItems
Type: boolean (default: false)
For JSON Schema draft 7, additionalItems are by default true, but this might create unintended types for arrays. Use this option to ignore default additionalItems for models as long as there are other types set for the array.
Note: ONLY use this option if you do not have control over the schema files you use to generate models from. Instead, you should adapt your schemas to be more strict by setting additionalItems: false.
Example:
1const generator = new TypeScriptGenerator({ 2 processorOptions: { 3 jsonSchema: { 4 ignoreAdditionalItems: true 5 } 6 } 7});
See the json-schema-ignore-additional-items example for a complete usage example.
For a comprehensive example demonstrating multiple processor options together, see the json-schema-processor-options example.
Interpretation of JSON Schema to CommonModel
The library transforms JSON Schema from data validation rules to data definitions (CommonModel(s)).
The algorithm tries to get to a model whose data can be validated against the JSON schema document.
As of now we only provide the underlying structure of the schema file for the model, where constraints/annotations such as maxItems, uniqueItems, multipleOf, etc. are not interpreted.
Patterns
Beside the regular interpreter we also look for certain patterns that are interpreted slightly differently.
oneOf with allOf
If both oneOf and allOf is present, each allOf model is merged into the interpreted oneOf.
For example take this example:
1{ 2 "allOf":[ 3 { 4 "title":"Animal", 5 "type":"object", 6 "properties":{ 7 "animalType":{ 8 "title":"Animal Type", 9 "type":"string" 10 }, 11 "age":{ 12 "type":"integer", 13 "min":0 14 } 15 } 16 } 17 ], 18 "oneOf":[ 19 { 20 "title":"Cat", 21 "type":"object", 22 "properties":{ 23 "animalType":{ 24 "const":"Cat" 25 }, 26 "huntingSkill":{ 27 "title":"Hunting Skill", 28 "type":"string", 29 "enum":[ 30 "clueless", 31 "lazy" 32 ] 33 } 34 } 35 }, 36 { 37 "title":"Dog", 38 "type":"object", 39 "additionalProperties":false, 40 "properties":{ 41 "animalType":{ 42 "const":"Dog" 43 }, 44 "breed":{ 45 "title":"Dog Breed", 46 "type":"string", 47 "enum":[ 48 "bulldog", 49 "bichons frise" 50 ] 51 } 52 } 53 } 54 ] 55}
Here animal is merged into cat and dog.
oneOf with properties
If both oneOf and properties are both present, it's interpreted exactly like oneOf with allOf. That means that the following:
1{ 2 "title":"Animal", 3 "type":"object", 4 "properties":{ 5 "animalType":{ 6 "title":"Animal Type", 7 "type":"string" 8 }, 9 "age":{ 10 "type":"integer", 11 "min":0 12 } 13 }, 14 "oneOf":[ 15 { 16 "title":"Cat", 17 "type":"object", 18 "properties":{ 19 "animalType":{ 20 "const":"Cat" 21 }, 22 "huntingSkill":{ 23 "title":"Hunting Skill", 24 "type":"string", 25 "enum":[ 26 "clueless", 27 "lazy" 28 ] 29 } 30 } 31 }, 32 { 33 "title":"Dog", 34 "type":"object", 35 "additionalProperties":false, 36 "properties":{ 37 "animalType":{ 38 "const":"Dog" 39 }, 40 "breed":{ 41 "title":"Dog Breed", 42 "type":"string", 43 "enum":[ 44 "bulldog", 45 "bichons frise" 46 ] 47 } 48 } 49 } 50 ] 51}
where all the defined behavior on the root object are merged into the two oneOf models cat and dog.
Interpreter
The main functionality is located in the Interpreter class. This class ensures to recursively create (or retrieve from a cache) a CommonModel representation of a Schema. We have tried to keep the functionality split out into separate functions to reduce complexity and ensure it is easy to maintain.
The order of interpretation:
trueboolean schema infers all model types (object,string,number,array,boolean,null,integer) schemas.typeinfers the initial model type.requiredare interpreted as is.patternPropertiesare merged together with any additionalProperties, where duplicate pattern models are merged.additionalPropertiesare interpreted as is, where duplicate additionalProperties for the model are merged. If the schema does not defineadditionalPropertiesit defaults totrueschema.additionalItemsare interpreted as is, where duplicate additionalItems for the model are merged. If the schema does not defineadditionalItemsit defaults totrueschema.itemsare interpreted as ether tuples or simple array, where more than 1 item are merged. Usage ofitemsinfersarraymodel type.propertiesare interpreted as is, where duplicatepropertiesfor the model are merged. Usage ofpropertiesinfersobjectmodel type.- allOf
dependenciesonly apply to schema dependencies, since property dependencies adds nothing to the underlying model. Any schema dependencies are interpreted and then merged together with the current interpreted model.enumis interpreted as is, where eachenum. Usage ofenuminfers the enumerator value type to the model, but only if the schema does not havetypespecified.constinterpretation overwrite already interpretedenum. Usage ofconstinfers the constant value type to the model, but only if the schema does not havetypespecified.- allOf/oneOf/anyOf/then/else
- not
Interpreting not schemas
not schemas infer the form for which the model should not take by recursively interpret the not schema. It removes certain model properties when encountered.
Currently, the following not model properties are interpreted:
typeenum
Restrictions
- You cannot use nested
notschemas to infer new model properties, it can only be used to re-allow them. - boolean
notschemas are not applied.
Processing sub schemas
The following JSON Schema keywords are merged with the already interpreted model:
allOfoneOfanyOfthenelse
Merging models
Because of the recursive nature of the interpreter (and the nested nature of JSON Schema) it happens that two models needs to be merged together.
If only one side has a property defined, it is used as is, if both have it defined they are merged based on the following logic (look here for more information about the CommonModel and its properties):
additionalPropertiesif both models contain it the two are recursively merged together.patternPropertiesif both models contain it each pattern model are recursively merged together.propertiesif both models contain the same property the corresponding models are recursively merged together.itemsare merged together based on a couple of rules:- If both models are simple arrays those item models are merged together as is.
- If both models are tuple arrays each tuple model (at specific index) is merged together.
- If either one side is different from the other, the tuple schemas is prioritized as it is more restrictive.
typesif both models contain types they are merged together, duplicate types are removed.enumif both models contain enums they are merged together, duplicate enums are removed.requiredif both models contain required properties they are merged together, duplicate required properties are removed.$id,$ref,extenduses left model value if present otherwise right model value if present.originalSchemaare overwritten.