Skip to content

Commit

Permalink
Typescript Property Renaming Fix (swagger-api#4264)
Browse files Browse the repository at this point in the history
* Implemented fix for missing json to property mapping in typescript-node
The previous version did not parse the JSON-Response at all, so that
properties, which where renamed (e. g.due to modelPropertyNaming config
option), were not correctly parsed.

E. g.: modelPropertyNaming=camelCase & property 'mounted_at' in json,
would be renamed to mountedAt in the model.
This was not parsed at all in the typescript-node client api, so that
the actual model still had the mounted_at property, but not mountedAt.

See swagger-api#2766 for additional details

* Updated samples for typescript-node

* Reverted initial changes to api.mustache

* Draft for object serializer for typescript-node

* Fixed missing variable error in ObjectSerializer in typescript-node

* Fix for body return type

* Fixed attributeTypeMaps when polymorphism is used

* Added ObjectSerializer support for polymorphism

* Code formatting in typescript-node api.mustache

* Fixed primitive type bug & added tests for ts-node
- primitives were serialized as strings instead of their respective type
- added test case for pet

* Code Formatting in ts-node client test
See samples/client/petstore/typescript-node/npm/client.ts

* Replaced tabs with 4 spaces and improved code formatting

* Recreated security test for typescript-node

* Read sample.png with fs.readFileSync instead of a stream
  • Loading branch information
TiFu authored and wing328 committed Feb 5, 2017
1 parent bd9f9ac commit cde7fc2
Show file tree
Hide file tree
Showing 13 changed files with 3,268 additions and 366 deletions.
1 change: 1 addition & 0 deletions modules/swagger-codegen/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/.settings/
/test-output/
/bin/
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,120 @@ let defaultBasePath = '{{basePath}}';
// ===============================================

/* tslint:disable:no-unused-variable */
let primitives = [
"string",
"boolean",
"double",
"integer",
"long",
"float",
"number",
"any"
];

class ObjectSerializer {
public static findCorrectType(data: any, expectedType: string) {
if (data == undefined) {
return expectedType;
} else if (primitives.indexOf(expectedType.toLowerCase()) !== -1) {
return expectedType;
} else if (expectedType === "Date") {
return expectedType;
} else {
if (enumsMap[expectedType]) {
return expectedType;
}

if (!typeMap[expectedType]) {
return expectedType; // w/e we don't know the type
}
// Check the discriminator
let discriminatorProperty = typeMap[expectedType].discriminator;
if (discriminatorProperty == null) {
return expectedType; // the type does not have a discriminator. use it.
} else {
if (data[discriminatorProperty]) {
return data[discriminatorProperty]; // use the type given in the discriminator
} else {
return expectedType; // discriminator was not present (or an empty string)
}
}
}
}
public static serialize(data: any, type: string) {
if (data == undefined) {
return data;
} else if (primitives.indexOf(type.toLowerCase()) !== -1) {
return data;
} else if (type.lastIndexOf("Array<", 0) === 0) { // string.startsWith pre es6
let subType: string = type.replace("Array<", ""); // Array<Type> => Type>
subType = subType.substring(0, subType.length - 1); // Type> => Type
let transformedData = [];
for (let index in data) {
let date = data[index];
transformedData.push(ObjectSerializer.serialize(date, subType));
}
return transformedData;
} else if (type === "Date") {
return data.toString();
} else {
if (enumsMap[type]) {
return data;
}
if (!typeMap[type]) { // in case we dont know the type
return data;
}
// get the map for the correct type.
let attributeTypes = typeMap[type].getAttributeTypeMap();
let instance = {};
for (let index in attributeTypes) {
let attributeType = attributeTypes[index];
instance[attributeType.baseName] = ObjectSerializer.serialize(data[attributeType.name], attributeType.type);
}
return instance;
}
}
public static deserialize(data: any, type: string) {
// polymorphism may change the actual type.
type = ObjectSerializer.findCorrectType(data, type);
if (data == undefined) {
return data;
} else if (primitives.indexOf(type.toLowerCase()) !== -1) {
return data;
} else if (type.lastIndexOf("Array<", 0) === 0) { // string.startsWith pre es6
let subType: string = type.replace("Array<", ""); // Array<Type> => Type>
subType = subType.substring(0, subType.length - 1); // Type> => Type
let transformedData = [];
for (let index in data) {
let date = data[index];
transformedData.push(ObjectSerializer.deserialize(date, subType));
}
return transformedData;
} else if (type === "Date") {
return new Date(data);
} else {
if (enumsMap[type]) {// is Enum
return data;
}
if (!typeMap[type]) { // dont know the type
return data;
}
let instance = new typeMap[type]();
let attributeTypes = typeMap[type].getAttributeTypeMap();
for (let index in attributeTypes) {
let attributeType = attributeTypes[index];
instance[attributeType.name] = ObjectSerializer.deserialize(data[attributeType.baseName], attributeType.type);
}
return instance;
}
}
}
{{#models}}
{{#model}}
Expand All @@ -29,6 +143,33 @@ export class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{
{{/description}}
'{{name}}': {{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{datatype}}}{{/isEnum}};
{{/vars}}

{{#discriminator}}
static discriminator = {{discriminator}};
{{/discriminator}}
{{^discriminator}}
static discriminator = undefined;
{{/discriminator}}

static attributeTypeMap: Array<{name: string, baseName: string, type: string}> = [
{{#vars}}
{
"name": "{{name}}",
"baseName": "{{baseName}}",
"type": "{{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{datatype}}}{{/isEnum}}"
}{{#hasMore}},
{{/hasMore}}
{{/vars}}
];

static getAttributeTypeMap() {
{{#parent}}
return super.getAttributeTypeMap().concat({{classname}}.attributeTypeMap);
{{/parent}}
{{^parent}}
return {{classname}}.attributeTypeMap;
{{/parent}}
}
}

{{#hasEnums}}
Expand All @@ -49,6 +190,28 @@ export namespace {{classname}} {
{{/model}}
{{/models}}

let enumsMap = {
{{#models}}
{{#model}}
{{#hasEnums}}
{{#vars}}
{{#isEnum}}
"{{datatypeWithEnum}}": {{datatypeWithEnum}},
{{/isEnum}}
{{/vars}}
{{/hasEnums}}
{{/model}}
{{/models}}
}

let typeMap = {
{{#models}}
{{#model}}
"{{classname}}": {{classname}},
{{/model}}
{{/models}}
}

export interface Authentication {
/**
* Apply authentication settings to header and query params.
Expand Down Expand Up @@ -212,19 +375,24 @@ export class {{classname}} {
{{/required}}{{/allParams}}
{{#queryParams}}
if ({{paramName}} !== undefined) {
queryParameters['{{baseName}}'] = {{paramName}};
queryParameters['{{baseName}}'] = ObjectSerializer.serialize({{paramName}}, "{{dataType}}");
}

{{/queryParams}}
{{#headerParams}}
headerParams['{{baseName}}'] = {{paramName}};

headerParams['{{baseName}}'] = ObjectSerializer.serialize({{paramName}}, "{{dataType}}");
{{/headerParams}}

let useFormData = false;

{{#formParams}}
if ({{paramName}} !== undefined) {
{{#isFile}}
formParams['{{baseName}}'] = {{paramName}};
{{/isFile}}
{{^isFile}}
formParams['{{baseName}}'] = ObjectSerializer.serialize({{paramName}}, "{{dataType}}");
{{/isFile}}
}
{{#isFile}}
useFormData = true;
Expand All @@ -244,7 +412,7 @@ export class {{classname}} {
encoding: null,
{{/isResponseFile}}
{{#bodyParam}}
body: {{paramName}},
body: ObjectSerializer.serialize({{paramName}}, "{{dataType}}")
{{/bodyParam}}
};

Expand All @@ -266,6 +434,9 @@ export class {{classname}} {
if (error) {
reject(error);
} else {
{{#returnType}}
body = ObjectSerializer.deserialize(body, "{{returnType}}");
{{/returnType}}
if (response.statusCode >= 200 && response.statusCode <= 299) {
resolve({ response: response, body: body });
} else {
Expand Down
Loading

0 comments on commit cde7fc2

Please sign in to comment.