@@ -279,6 +279,18 @@ def canonicalish(schema: JSONType) -> Dict[str, Any]:
279
279
elif len (enum_ ) == 1 :
280
280
return {"const" : enum_ [0 ]}
281
281
return {"enum" : enum_ }
282
+ # if/then/else schemas are ignored unless if and another are present
283
+ if_ = schema .pop ("if" , None )
284
+ then = schema .pop ("then" , schema )
285
+ else_ = schema .pop ("else" , schema )
286
+ if if_ is not None and (then is not schema or else_ is not schema ):
287
+ schema = {
288
+ "anyOf" : [
289
+ {"allOf" : [if_ , then , schema ]},
290
+ {"allOf" : [{"not" : if_ }, else_ , schema ]},
291
+ ]
292
+ }
293
+ assert isinstance (schema , dict )
282
294
# Recurse into the value of each keyword with a schema (or list of them) as a value
283
295
for key in SCHEMA_KEYS :
284
296
if isinstance (schema .get (key ), list ):
@@ -538,12 +550,6 @@ def canonicalish(schema: JSONType) -> Dict[str, Any]:
538
550
if (not one_of ) or one_of .count (TRUTHY ) > 1 :
539
551
return FALSEY
540
552
schema ["oneOf" ] = one_of
541
- # if/then/else schemas are ignored unless if and another are present
542
- if "if" not in schema :
543
- schema .pop ("then" , None )
544
- schema .pop ("else" , None )
545
- if "then" not in schema and "else" not in schema :
546
- schema .pop ("if" , None )
547
553
if schema .get ("uniqueItems" ) is False :
548
554
del schema ["uniqueItems" ]
549
555
return schema
@@ -761,8 +767,6 @@ def merged(schemas: List[Any]) -> Optional[Schema]:
761
767
out ["not" ] = {"anyOf" : [out ["not" ], s .pop ("not" )]}
762
768
763
769
# TODO: merge `items` schemas or lists-of-schemas
764
- # TODO: merge if/then/else schemas to the chained form
765
- # or maybe canonicalise them to an anyOf instead?
766
770
# TODO: merge dependencies
767
771
768
772
# This loop handles the remaining cases. Notably, we do not attempt to
@@ -772,6 +776,7 @@ def merged(schemas: List[Any]) -> Optional[Schema]:
772
776
# - `$ref`; if not already resolved we can't do that here
773
777
# - `anyOf`; due to product-like explosion in worst case
774
778
# - `oneOf`; which we plan to handle as an anyOf-not composition
779
+ # - `if`/`then`/`else`; which is removed by canonicalisation
775
780
for k , v in s .items ():
776
781
if k not in out :
777
782
out [k ] = v
0 commit comments