@@ -1763,3 +1763,91 @@ class CreateObjectDto(BaseModel):
17631763 'type' : 'object' ,
17641764 },
17651765 }
1766+
1767+
1768+ def test_nested_discriminator () -> None :
1769+ """
1770+ The exact details of the JSON schema produced are not necessarily important; the test was added in response to a
1771+ regression that caused the inner union to lose its discriminator. Even if the schema changes, the important
1772+ thing is that the core schema (and therefore JSON schema) produced has an actual discriminated union in it.
1773+ For more context, see: https://github.com/pydantic/pydantic/issues/8688.
1774+ """
1775+
1776+ class Step_A (BaseModel ):
1777+ type : Literal ['stepA' ]
1778+ count : int
1779+
1780+ class Step_B (BaseModel ):
1781+ type : Literal ['stepB' ]
1782+ value : float
1783+
1784+ class MyModel (BaseModel ):
1785+ type : Literal ['mixed' ]
1786+ sub_models : List ['SubModel' ]
1787+ steps : Union [Step_A , Step_B ] = Field (
1788+ default = None ,
1789+ discriminator = 'type' ,
1790+ )
1791+
1792+ class SubModel (MyModel ):
1793+ type : Literal ['mixed' ]
1794+ blending : float
1795+
1796+ MyModel .model_rebuild ()
1797+ assert MyModel .model_json_schema () == {
1798+ '$defs' : {
1799+ 'Step_A' : {
1800+ 'properties' : {
1801+ 'count' : {'title' : 'Count' , 'type' : 'integer' },
1802+ 'type' : {'const' : 'stepA' , 'title' : 'Type' },
1803+ },
1804+ 'required' : ['type' , 'count' ],
1805+ 'title' : 'Step_A' ,
1806+ 'type' : 'object' ,
1807+ },
1808+ 'Step_B' : {
1809+ 'properties' : {
1810+ 'type' : {'const' : 'stepB' , 'title' : 'Type' },
1811+ 'value' : {'title' : 'Value' , 'type' : 'number' },
1812+ },
1813+ 'required' : ['type' , 'value' ],
1814+ 'title' : 'Step_B' ,
1815+ 'type' : 'object' ,
1816+ },
1817+ 'SubModel' : {
1818+ 'properties' : {
1819+ 'blending' : {'title' : 'Blending' , 'type' : 'number' },
1820+ 'steps' : {
1821+ 'default' : None ,
1822+ 'discriminator' : {
1823+ 'mapping' : {'stepA' : '#/$defs/Step_A' , 'stepB' : '#/$defs/Step_B' },
1824+ 'propertyName' : 'type' ,
1825+ },
1826+ 'oneOf' : [{'$ref' : '#/$defs/Step_A' }, {'$ref' : '#/$defs/Step_B' }],
1827+ 'title' : 'Steps' ,
1828+ },
1829+ 'sub_models' : {'items' : {'$ref' : '#/$defs/SubModel' }, 'title' : 'Sub Models' , 'type' : 'array' },
1830+ 'type' : {'const' : 'mixed' , 'title' : 'Type' },
1831+ },
1832+ 'required' : ['type' , 'sub_models' , 'blending' ],
1833+ 'title' : 'SubModel' ,
1834+ 'type' : 'object' ,
1835+ },
1836+ },
1837+ 'properties' : {
1838+ 'steps' : {
1839+ 'default' : None ,
1840+ 'discriminator' : {
1841+ 'mapping' : {'stepA' : '#/$defs/Step_A' , 'stepB' : '#/$defs/Step_B' },
1842+ 'propertyName' : 'type' ,
1843+ },
1844+ 'oneOf' : [{'$ref' : '#/$defs/Step_A' }, {'$ref' : '#/$defs/Step_B' }],
1845+ 'title' : 'Steps' ,
1846+ },
1847+ 'sub_models' : {'items' : {'$ref' : '#/$defs/SubModel' }, 'title' : 'Sub Models' , 'type' : 'array' },
1848+ 'type' : {'const' : 'mixed' , 'title' : 'Type' },
1849+ },
1850+ 'required' : ['type' , 'sub_models' ],
1851+ 'title' : 'MyModel' ,
1852+ 'type' : 'object' ,
1853+ }
0 commit comments