11"""JSON schema support for Odin."""
22import json
3- from typing import Any , Dict , Final , Sequence , TextIO , Type
3+ from typing import Any , Dict , Final , List , Sequence , TextIO , Type , Union
44
55import odin
66from odin .registration import get_child_resources
1313class JSONSchema :
1414 """JSON Schema representation of an Odin resource."""
1515
16- def __init__ (self , resource : Type [ResourceBase ]):
16+ def __init__ (
17+ self , resource : Type [ResourceBase ], * , require_type_field : bool = True
18+ ):
1719 self .resource = resource
20+ self .require_type_field = require_type_field
1821
1922 self .defs = {}
2023
@@ -44,7 +47,8 @@ def _resource_to_schema(self, meta: ResourceOptions) -> Dict[str, Any]:
4447 def _required_fields (self , meta : ResourceOptions ) -> Sequence [str ]:
4548 """Get a list of required fields."""
4649 required = [field .name for field in meta .fields if not field .null ]
47- required .append (meta .type_field )
50+ if self .require_type_field :
51+ required .append (meta .type_field )
4852 return required
4953
5054 def _fields_to_properties (self , meta : ResourceOptions ) -> Dict [str , Any ]:
@@ -61,14 +65,32 @@ def _field_to_schema(self, field: odin.Field) -> Dict[str, Any]:
6165 return self ._composite_field_to_schema (field )
6266
6367 schema = {
64- "type" : "string" ,
68+ "type" : self . _field_type ( field ) ,
6569 "description" : field .doc_text or "" ,
6670 }
6771 if field .choices :
6872 schema ["enum" ] = tuple (str (value ) for value in field .choice_values )
6973
7074 return schema
7175
76+ def _field_type (self , field : odin .Field ) -> Union [str , List [str ]]:
77+ """Get the type of a field."""
78+
79+ if isinstance (field , odin .ListField ):
80+ type_name = "array"
81+ elif isinstance (field , odin .IntegerField ):
82+ type_name = "integer"
83+ elif isinstance (field , odin .FloatField ):
84+ type_name = "number"
85+ elif isinstance (field , odin .BooleanField ):
86+ type_name = "boolean"
87+ elif isinstance (field , odin .DictField ):
88+ type_name = "object"
89+ else :
90+ type_name = "string"
91+
92+ return [type_name , "null" ] if field .null else type_name
93+
7294 def _composite_field_to_schema (self , field : odin .CompositeField ) -> Dict [str , Any ]:
7395 """Convert a composite field to a JSON schema."""
7496
0 commit comments