In the improved Python SDK, fields of a custom type can now differentiate between a nullable value and a missing value and will operate according to the behavior of the type specified. This way you can either pass a value that corresponds to the type specified, use null
as a value or skip the field altogether depending upon the defined behavior of the field.
Details
We are delighted to announce support for optional and nullable fields within custom types in Python SDKs. Fields of custom type can be marked as nullable
and optional
based on what the intended behavior is for that particular field.
A property marked as optional
means that the user can either pass the value that conforms with the type specified or can skip that value altogether. Whereas, if a field is marked as nullable
, then the user can either pass the value that corresponds to the type defined or use a nullable value.
Other combinations are also possible using this flag, which will be discussed later in the changelog.
What was Supported Before?
Previously, the Python SDK didn't support optional
or nullable
flags for the fields of a model. Both these flags were equally treated, meaning if either one of the flags was true for any field of a model, it would be treated as a nullable value. Hence null value was accepted in either case.
What has Changed?
Functionality of fields within custom type
Now the latest Python SDK respects the Optional and Nullable settings in their true form. The table below shows how the optional and nullable settings affect the serialization of different values:
Nullable = true | Nullable = false | |
---|---|---|
Optional = true |
{} , {"key":value} , {"key:null} |
{} , {"key":value} |
Optional = false (required) |
{"key":value} , {"key":null} |
{"key":value} |
- Optional means that if no value is provided, then it should be ignored during serialization.
- Non-Optional (required) means that the key has to be included in JSON irrespective of the value.
- Nullable means that value of the key can be null.
- Non-Nullable means that value of the key cannot be null.
Current changed behavior in Python
Optional = true, Nullable = true An uninitialized field will be ignored in JSON during serialization. And if a proper value is assigned, then it will not be ignored.
Optional = true, Nullable = false An uninitialized field will be ignored in JSON during serialization. And if a proper value is assigned, then it is not ignored. A nullable value will throw an error.
Optional = false, Nullable = true Field must be included in JSON representation and it can have null its value.
Optional = false, Nullable = false Field must be included in JSON representation and it cannot have null as a value. In case of a missing or null value, an exception will be thrown.
Changes in Oneof and Anyof Model fields Another noticeable change introduced is the support for optional and nullable fields with custom types using
oneOf
andanyOf
keywords. For example, if a value of a field can be one of the custom typesMorning
orEvening
, then the Python SDK should accept either of the two incoming values exactly matching one of the schemas. However, if a field is marked as bothoptional
andnullable
, then this means:An incoming null value is acceptable because the
nullable
flag is trueField could be missing altogether because the
optional
flag is true
This is how the API specification looks like for the example explained in APIMatic format:
{
"Name": "SimpleCase",
"ImplementationType": "Structure",
"Description": "This class contains simple case of oneOf.",
"Fields": [
{
"Optional": true,
"OneOfTypes": [
{
"Type": "Morning",
"IsSdlNativeType": false,
"Constant": false,
"DefaultValue": "",
"Nullable": false,
"IsArray": false,
"IsMap": false,
"IsArrayOfMap": false
},
{
"Type": "Evening",
"IsSdlNativeType": false,
"Constant": false,
"DefaultValue": "",
"Nullable": false,
"IsArray": false,
"IsMap": false,
"IsArrayOfMap": false
}
],
"Type": "Object",
"IsSdlNativeType": true,
"Constant": false,
"IsStream": false,
"IsAttribute": false,
"Attributes": {},
"Nullable": true,
"IsArray": false,
"IsMap": false,
"IsArrayOfMap": false,
"Deprecated": false,
"Name": "session",
"Description": "Course session",
"DefaultValue": ""
}
],
"Deprecated": false
}
The accepted values for this schema are:
{
"session": {
"startsAt": "startsAt9",
"endsAt": "endsAt9",
"offerLunch": true
}
}
Or:
{
"session": {
"startsAt": "startsAt9",
"endsAt": "endsAt9",
"offerDinner": true
}
}
Or:
{ "session": null
}
Or, in case the optional
field is missing:
{ }
Changes in Deserialization of Custom Types
The support for optional
and nullable
settings has also changed the behavior of how the fields of a custom type are deserialized into their respective types. Previously, optional
and nullable
properties were treated in a similar manner. This means that if a value for a certain field was missing, it would automatically be initialed with the value None
. And if a nullable
value was missing, it would also be initialized as None
. However with the latest changes, if an optional field's value is missing, that property will not be initialized in the model.