Skip to main content

Discriminated Unions and Enum Defaults in Python v4 SDKs (Beta)

· 2 min read

Python v4 SDKs now resolve discriminated unions precisely. A oneOf union or an allOf hierarchy that declares a discriminator is tagged by the wire key, so the SDK picks the right variant on the way in and writes the right tag on the way out, even when the variant model does not declare the tag field itself.

Details​

Discriminated unions​

A discriminated union is a type alias over its variants, read through the runtime's WireDiscriminator. On deserialization it reads the discriminator property your specification names and returns the matching variant, so you narrow the result with isinstance or match on its class rather than on a tag string. On serialization the union writes the tag for the variant you built. Polymorphic allOf hierarchies are handled the same way as oneOf unions.

Dict companions and enum defaults​

Every model now has a {Model}Dict companion, a closed TypedDict with the same fields, so any parameter that takes a model also takes a plain dictionary and your type checker still checks its keys. A union's dictionary spelling carries the tag key, because a bare dictionary has no class to read it from. An enum property with a default in the specification now defaults to that member in the generated model.

Usage Example​

Send the variant you mean as a model or a dictionary, and narrow what comes back on its class:

from payments import PaymentsClient
from payments.models import BankPayment, CardPayment

client = PaymentsClient(bearer_auth="YOUR_ACCESS_TOKEN")

# The union writes the "paymentType" tag; currency takes the spec's default, Currency.USD.
payment = client.payments.create_payment(CardPayment(card_token="tok_visa", amount=1000))

# The dictionary spelling carries the tag itself.
client.payments.create_payment({"paymentType": "bank", "iban": "DE89370400440532013000", "amount": 1000})

# The response arrives as the matching variant.
match payment:
case CardPayment() as card:
print("Card ending", card.last4)
case BankPayment() as bank:
print("Bank transfer from", bank.iban)

A dictionary without the tag key raises a pydantic ValidationError (union_tag_not_found) at the call.

This feature is available in the Python v4 SDK (beta). Generate it from the APIMatic CLI:

apimatic sdk generate --language=python --codegen-version=v4 --stability=beta

For the full set of flags and options, see the APIMatic CLI documentation.