Note
|
Feedback in terms of issues appreciated! |
This is intended to be submitted back to the OpenAPI Generator crew because there are a number of tickets raised around its:
-
poor serialization and deserialization of data,
-
date formatting
-
support for alternative formats (such as uuids, emails, etc),
-
lack of serialization overrides (if you have a format we don’t support you can add in your own custom serializer for it)
-
honours Javascript style formatting for variable names, properly swapping back and forth between the two (e.g.
snake_case
→snakeCase
,@id
→_id
) -
incomplete types when multiple return codes exist and support different return objects
-
support oneOf’s and discriminators
-
OpenAPI 5.x brings the Set<> type to the party and it does not work at all as expected. We recommend you use the
useEnhancedSerializer
mechanism for this otherwise stuff just isn’t going to work.
At the moment it is generating "correct" code, and the serialization works for simple types and is tested with those types. It needs more exhaustive testing around:
-
arrays
-
deep nested objects
-
date and date-times
-
additionalProperty types (i.e. Record types)
-
2.1 - swaps to 7.x of the OpenAPI generator. Updates the way that serialization happens for inheritance as well.
it might:
-
being able to understand the full hierarchy of a "type" and determine if any of the types down the tree would cause serialization issues and allow a flag to bypass and just use the returned object as is. This would mean it wouldn’t support classes or serialization overrides.
Download and build this project. Download the OpenAPI 5.0.0-SNAPSHOT.jar file (see below).
We use an additional property to trigger the extensions so it remains backwards compatible and won’t mess with people’s existing code:
--additional-properties useEnhancedSerializer
This property will give you back a pure AxiosResponse<T> or AxiosError<T> which will in fact not be deserialized. To do that you will need to manually call ObjectSerializer.deserialize(data.data, 'type'). Otherwise it will be the raw json object.
If you wish to have it automatically deserialized, use
--additional-properties useCoalesceReturnTypes
If you wish to use optimized deserialization techniques for primitive data types and their arrays, add no extra options. If however you need to be able to intercept all deserialization, add in
--additional-properties useNonOptimalDeserialization
And then your return types will be all of the possible return types from that method and it will check the status code for you and deserialize into the correct type.
Note
|
the type of generator is currently typescript-axios-enhanced .
|
java -cp "openapi-generator-cli-5.0.0-SNAPSHOT.jar:openapi-tsaxios-generator-1.1-SNAPSHOT.jar" org.openapitools.codegen.OpenAPIGenerator generate -i api.yaml -g typescript-axios-enhanced --additional-properties supportsES6 --additional-properties nullSafeAdditionalProps --additional-properties useEnhancedSerializer=true -o api
As we are currently using the 5.0.0-SNAPSHOT because the API changed a bit, getting the snapshot jar is a little more tricky.
You need to download the Maven metadata file from here .
Once you have done this, you will find references to the current releases in a format similar to below. Find the value
reference and that
is the jar filename. Then you can grab this from the reference https://oss.sonatype.org/content/repositories/snapshots/org/openapitools/openapi-generator/5.0.0-SNAPSHOT/openapi-generator-maven-plugin-VALUE.jar
Where VALUE is the value from the value
field.
<snapshotVersion>
<extension>jar</extension>
<value>5.0.0-20200722.171336-430</value>
<updated>20200722171336</updated>
</snapshotVersion>
Party for example is created like this:
export class Party {
/**
*
* @type {PartyType}
* @memberof Party
*/
public partyType: PartyType;
/**
*
* @type {string}
* @memberof Party
*/
public givenName: string;
/**
*
* @type {string}
* @memberof Party
*/
public additionalName?: string;
/**
*
* @type {string}
* @memberof Party
*/
public familyName: string;
/**
*
* @type {string}
* @memberof Party
*/
public telephone?: string;
/**
*
* @type {string}
* @memberof Party
*/
public email: string;
/**
*
* @type {Date}
* @memberof Party
*/
public birthDate?: Date;
constructor(init?: Partial<Party>) {
Object.assign(this, init);
}
}
The partial is used to allow people to create the class as they have been.
for this is also generates a hidden serializer/deserializer. This is outside because toJson() has semantics in Javascript:
class PartyTypeTransformer {
static toJson(val: Party): any {
const data: any = {};
if (val.partyType) {
data['partyType'] = ObjectSerializer.serialize(val.partyType, 'PartyType');
}
if (val.givenName) {
data['givenName'] = ObjectSerializer.serialize(val.givenName, 'string');
}
if (val.additionalName) {
data['additionalName'] = ObjectSerializer.serialize(val.additionalName, 'string');
}
if (val.familyName) {
data['familyName'] = ObjectSerializer.serialize(val.familyName, 'string');
}
if (val.telephone) {
data['telephone'] = ObjectSerializer.serialize(val.telephone, 'string');
}
if (val.email) {
data['email'] = ObjectSerializer.serialize(val.email, 'email');
}
if (val.birthDate) {
data['birthDate'] = ObjectSerializer.serialize(val.birthDate, 'date');
}
return data;
}
// expect this to be a decoded value
static fromJson(val: any): Party {
const init = {
partyType: ObjectSerializer.deserialize(val['partyType'], 'PartyType'),
givenName: ObjectSerializer.deserialize(val['givenName'], 'string'),
additionalName: ObjectSerializer.deserialize(val['additionalName'], 'string'),
familyName: ObjectSerializer.deserialize(val['familyName'], 'string'),
telephone: ObjectSerializer.deserialize(val['telephone'], 'string'),
email: ObjectSerializer.deserialize(val['email'], 'email'),
birthDate: ObjectSerializer.deserialize(val['birthDate'], 'date'),
};
return new Party(init);
}
}
The toJson uses if
to determine if there is a value to ensure it does not send the field at all if there is no value.
This mechanism is also used for the additionalProperties
style capability.
The serializer/deserializer is extendable and generates appropriate code for all types in one serializer.