-
Notifications
You must be signed in to change notification settings - Fork 6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Swift4: make generated models structs instead of classes #7345
Conversation
This fixes issue swagger-api#6941. In this change, we make our Swift4 generated model objects struct instead of class. However, in order to do this, we needed to handle the following edge cases: * Inheritance and polymorphism (allOf) * With classes, we use inheritance. So therefore, the parent properties are ONLY on the parent generated class, and the model object which derives from the parent class picks up those properties through inheritance. * However, structs do not support inheritance. So we simply duplicate the parent allOf properties in the child struct. * We have to handle the case where the property name on the struct may be different than the property name in the JSON. By default, the Codable protocol assumes that the JSON property name is the same as the struct property name. If they need to be different, then we generate a CodingKeys string enum, which contains the mapping between struct property name and JSON property name. * additionalProperties. We cannot use the default Codable implementation for the additionalProperties, since it will look for an actual dictionary called "additionalProperties" in the JSON. Therefore, for model objects which have additionalProperties, we must generate our own implementation for the Decodable and Encodable protocols. I have run ./bin/swift4-all.sh and ./bin/swift4-test.sh to re-generate all of the sources, and I have verified that the generated code in samples/clients/test/swift4/default builds and the unit tests pass.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cool change! thx @ehyche
Hello @ehyche ! Really nice work, I have started a few weeks ago to look into the swift4 generator. Was wondering if this PR includes check for required fields on the swagger file, and generates the objects adding "!" and "?" I see in one of you examples:
cardType there be nor optional right? Thanks in advance! |
Hello @ehyche enums can contain the case "open", also properties can be named like that. Or does anything speak against this suggestion? Big thanks for your great work! |
PR checklist
./bin/
to update Petstore sample so that CIs can verify the change. (For instance, only need to run./bin/{LANG}-petstore.sh
and./bin/security/{LANG}-petstore.sh
if updating the {LANG} (e.g. php, ruby, python, etc) code generator or {LANG} client's mustache templates). Windows batch files can be found in.\bin\windows\
.3.0.0
branch for changes related to OpenAPI spec 3.0. Default:master
.Description of the PR
This addresses this issue: #6941
Previously, our generated model objects were classes. For example, if we had the following definition:
then our generated model would be a class like this:
There are a couple of things we would like to improve here:
In other words, we would like our generated model to just look like:
For simple cases like this, just claiming conformance to the Codable protocol in Swift is all that is needed. Just by doing this we get complete serialization and de-serialization support.
However, there are a few cases where we have to provide an additional implementation beyond just claiming Codable conformance as we do above. These are listed in the sections below.
When the struct property is not the same as the JSON property
If we had the following definition:
Then this has a JSON property called "for". However, when we create the property on the struct, then we cannot call the struct property "for" since that is a Swift reserved word. So we escape the JSON property "for" into a struct property called "_for".
We have to tell the Codable protocol when something like this happens - when the name of the struct property is different than the name of the JSON property. We do this by providing a string enum that conforms to the CodingKey protocol.
So therefore our VariableNameTest definition generates this struct:
In this PR we also make a change to the codegen module to:
When we have additionalProperties
Suppose we have a definition with both properties and additionalProperties:
The generated struct would look like this:
However, the default implementation of Codable that the Swift Standard Library provides will not work in this case, because it will attempt to serialize/de-serialize a dictionary called "additionalProperties", which is not how additionalProperties is supposed to be serialized.
So therefore, in the case where we have additionalProperties, then we must provide our own implementation of the Codable protocol.
When we have polymorphism
When we have polymorphism in our definitions, like this:
Then previously we generated classes and used inheritance:
But in Swift, as with most languages, structs cannot use inheritance. So therefore, since we are using structs, then we will simply duplicate the properties in the base definition in the derived definitions:
This means that we had to change our templates to use "allVars" (which include parent properties) instead of "vars" (which only includes the properties defined on the definition itself).