Skip to content

Commit

Permalink
Merge pull request #366 from amarzavery/default
Browse files Browse the repository at this point in the history
serialization updates
  • Loading branch information
amarzavery authored Jul 11, 2019
2 parents 1ccabcc + 4c0025a commit 401b56e
Show file tree
Hide file tree
Showing 7 changed files with 249 additions and 6 deletions.
6 changes: 6 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
# Changelog
## 2.0.3 - 2019-07-11
- Added support to not send default values while sending the request.
- Added support to populate entities with it's default value if it is present in the mapper while deserializing the response.
- During deserialization, if the service does not provide the discriminator property then we set it. While setting the discriminator property, we compare model property name and the `clientName` of the `polymorphicDiscriminator` instead of the `serializedName` of the `polymorphicDiscriminator`.
- Added tests for serializing and deserializing additional properties.

## 2.0.2 - 2019-07-08
- Updated `cookieJar.setCookie()` with `{ ignoreError: true }` for `NodeFetchHttpClient`. This should silently ignore things like parse errors and invalid domains. This should resolve issues where customers using the `@azure/arm-appservice` package get an error due to mismatch in the domain [Azure/azure-sdk-for-js#1008](https://github.com/Azure/azure-sdk-for-js/issues/1008). This behavior makes it consistent with the old package [azure-arm-website](https://www.npmjs.com/package/azure-arm-website) which depends on the runtime [ms-rest](https://www.npmjs.com/package/ms-rest) that depends on the [request](https://www.npmjs.com/package/request) library which uses the [tough-cookie](https://www.npmjs.com/package/tough-cookie) package in `{ looseMode: true }` by [default](https://github.com/request/request/blob/536f0e76b249e4545c3ba2ac75e643146ebf3824/lib/cookies.js#L21) with `{ ignoreError: true }` as can be seen [here](https://github.com/request/request/blob/df346d8531ac4b8c360df301f228d5767d0e374e/request.js#L969).

Expand Down
19 changes: 16 additions & 3 deletions lib/serializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export class Serializer {
payload = [];
}

if (object == undefined && (mapper.defaultValue != undefined || mapper.isConstant)) {
if (mapper.isConstant) {
object = mapper.defaultValue;
}

Expand Down Expand Up @@ -159,6 +159,10 @@ export class Serializer {
// so let's do the more user-friendly thing and return an empty list.
responseBody = [];
}
// specifically check for undefined as default value can be a falsey value `0, "", false, null`
if (mapper.defaultValue !== undefined) {
responseBody = mapper.defaultValue;
}
return responseBody;
}

Expand Down Expand Up @@ -597,7 +601,16 @@ function deserializeCompositeType(serializer: Serializer, mapper: CompositeMappe
}
propertyInstance = res;
const polymorphicDiscriminator = mapper.type.polymorphicDiscriminator;
if (polymorphicDiscriminator && propertyMapper.serializedName === polymorphicDiscriminator.serializedName && propertyInstance == undefined) {
// checking that the model property name (key)(ex: "fishtype") and the
// clientName of the polymorphicDiscriminator {metadata} (ex: "fishtype")
// instead of the serializedName of the polymorphicDiscriminator (ex: "fish.type")
// is a better approach. The generator is not consistent with escaping '\.' in the
// serializedName of the property (ex: "fish\.type") that is marked as polymorphic discriminator
// and the serializedName of the metadata polymorphicDiscriminator (ex: "fish.type"). However,
// the clientName transformation of the polymorphicDiscriminator (ex: "fishtype") and
// the transformation of model property name (ex: "fishtype") is done consistently.
// Hence, it is a safer bet to rely on the clientName of the polymorphicDiscriminator.
if (polymorphicDiscriminator && key === polymorphicDiscriminator.clientName && propertyInstance == undefined) {
propertyInstance = mapper.serializedName;
}

Expand All @@ -606,7 +619,7 @@ function deserializeCompositeType(serializer: Serializer, mapper: CompositeMappe
if (Array.isArray(responseBody[key]) && modelProps[key].serializedName === "") {
propertyInstance = responseBody[key];
instance = serializer.deserialize(propertyMapper, propertyInstance, propertyObjectName);
} else if (propertyInstance !== undefined) {
} else if (propertyInstance !== undefined || propertyMapper.defaultValue !== undefined) {
serializedValue = serializer.deserialize(propertyMapper, propertyInstance, propertyObjectName);
instance[key] = serializedValue;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/util/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const Constants = {
* @const
* @type {string}
*/
msRestVersion: "2.0.2",
msRestVersion: "2.0.3",

/**
* Specifies HTTP.
Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"email": "azsdkteam@microsoft.com",
"url": "https://github.com/Azure/ms-rest-js"
},
"version": "2.0.2",
"version": "2.0.3",
"description": "Isomorphic client Runtime for Typescript/node.js/browser javascript client libraries generated using AutoRest",
"tags": [
"isomorphic",
Expand Down Expand Up @@ -97,7 +97,6 @@
"mocha-multi-reporters": "^1.1.7",
"npm-run-all": "^4.1.5",
"nyc": "^14.1.1",
"opn-cli": "^5.0.0",
"rollup": "^1.16.6",
"rollup-plugin-alias": "^1.5.2",
"rollup-plugin-commonjs": "^10.0.1",
Expand Down
75 changes: 75 additions & 0 deletions test/data/TestClient/lib/models/mappers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,81 @@ internalMappers.Pet = {
}
}
};
internalMappers.PetAP = {
required: false,
serializedName: "PetAP",
type: {
name: "Composite",
additionalProperties: {
type: {
name: "String"
}
},
className: "PetAP",
modelProperties: {
id: {
required: true,
serializedName: "id",
type: {
name: "Number"
}
},
name: {
required: false,
serializedName: "name",
type: {
name: "String"
}
},
eyeColor: {
required: true,
serializedName: "eyeColor",
isConstant: true,
defaultValue: "brown",
type: {
name: "String"
}
},
favoriteFood: {
required: false,
serializedName: "favoriteFood",
defaultValue: "bones",
type: {
name: "String"
}
},
status: {
required: false,
readOnly: true,
serializedName: "status",
type: {
name: "Boolean"
}
},
odatalocation: {
required: true,
serializedName: "@odata\\.location",
type: {
name: "String"
}
},
additionalProperties1: {
required: false,
serializedName: "additionalProperties",
type: {
name: "Dictionary",
value: {
required: false,
serializedName: "NumberElementType",
type: {
name: "Number"
}
}
}
}
}
}
};
internalMappers.PetGallery = {
required: false,
serializedName: "PetGallery",
Expand Down
150 changes: 150 additions & 0 deletions test/serializationTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,38 @@ describe("msrest", function () {
done();
});

it("should correctly serialize additionalProperties when the mapper knows that additional properties are allowed", function () {
const bodyParameter = {
id: 5,
name: "Funny",
odatalocation: "westus",
additionalProperties1: {
height: 5.61,
weight: 599,
footsize: 11.5
},
color: "red",
city: "Seattle",
food: "tikka masala",
birthdate: "2017-12-13T02:29:51.000Z"
};
const client = new TestClient("http://localhost:9090");
const mapper = Mappers.PetAP;
const result = client.serializer.serialize(mapper, bodyParameter, "bodyParameter");
result.id.should.equal(5);
result.eyeColor.should.equal("brown");
assert.isUndefined(result.favoriteFood);
result["@odata.location"].should.equal("westus");
result.color.should.equal("red");
result.city.should.equal("Seattle");
result.food.should.equal("tikka masala");
result.additionalProperties.height.should.equal(5.61);
result.additionalProperties.weight.should.equal(599);
result.additionalProperties.footsize.should.equal(11.5);
result.name.should.equal("Funny");
result.birthdate.should.equal("2017-12-13T02:29:51.000Z");
});

it("should allow null when required: true and nullable: true", function () {
const mapper: msRest.Mapper = {
required: false,
Expand Down Expand Up @@ -1058,6 +1090,124 @@ describe("msrest", function () {
done();
});

it("should correctly deserialize additionalProperties when the mapper knows that additional properties are allowed", function (done) {
const responseBody = {
id: 5,
name: "Funny",
status: true,
"@odata.location": "westus",
additionalProperties: {
height: 5.61,
weight: 599,
footsize: 11.5
},
color: "red",
city: "Seattle",
food: "tikka masala",
birthdate: "2017-12-13T02:29:51Z"
};
const client = new TestClient("http://localhost:9090");
const mapper = Mappers.PetAP;
const result = client.serializer.deserialize(mapper, responseBody, "responseBody");
result.id.should.equal(5);
result.status.should.equal(true);
result.eyeColor.should.equal("brown");
result.favoriteFood.should.equal("bones");
result.odatalocation.should.equal("westus");
result.color.should.equal("red");
result.city.should.equal("Seattle");
result.food.should.equal("tikka masala");
result.birthdate.should.equal("2017-12-13T02:29:51Z");
result.additionalProperties1.height.should.equal(5.61);
result.additionalProperties1.weight.should.equal(599);
result.additionalProperties1.footsize.should.equal(11.5);
result.name.should.equal("Funny");
done();
});

it("should correctly deserialize without failing when encountering no discriminator", function (done) {
const client = new TestClient("http://localhost:9090");
const mapper = Mappers.Fish;
const responseBody = {
"age": 22,
"birthday": new Date("2012-01-05T01:00:00Z").toISOString(),
"species": "king",
"length": 1.0,
"picture": Buffer.from([255, 255, 255, 255, 254]).toString(),
"siblings": [
{
"fish.type": "mutatedshark",
"age": 105,
"birthday": new Date("1900-01-05T01:00:00Z").toISOString(),
"length": 10.0,
"picture": Buffer.from([255, 255, 255, 255, 254]).toString(),
"species": "dangerous",
"siblings": [
{
"fish.type": "mutatedshark",
"age": 6,
"length": 20.0,
"species": "predator"
}
]
}
]
};
const deserializedSawshark = client.serializer.deserialize(mapper, responseBody, "responseBody");
deserializedSawshark.fishtype.should.equal("Fish");
deserializedSawshark.siblings.length.should.equal(1);
deserializedSawshark.siblings[0].fishtype.should.equal("mutatedshark");
deserializedSawshark.siblings[0].species.should.equal("dangerous");
deserializedSawshark.siblings[0].birthday.should.equal("1900-01-05T01:00:00.000Z");
deserializedSawshark.siblings[0].age.should.equal(105);
deserializedSawshark.siblings[0].siblings[0].fishtype.should.equal("mutatedshark");
deserializedSawshark.siblings[0].siblings[0].species.should.equal("predator");
deserializedSawshark.siblings[0].siblings[0].age.should.equal(6);
done();
});

it("should correctly serialize without failing when encountering no discriminator", function (done) {
const client = new TestClient("http://localhost:9090");
const mapper = Mappers.SawShark;
const sawshark = {
"age": 22,
"birthday": new Date("2012-01-05T01:00:00Z"),
"species": "king",
"length": 1.0,
"picture": Buffer.from([255, 255, 255, 255, 254]),
"siblings": [
{
"fishtype": "shark",
"age": 6,
"birthday": new Date("2012-01-05T01:00:00Z"),
"length": 20.0,
"species": "predator"
},
{
"fishtype": "sawshark",
"age": 105,
"birthday": new Date("1900-01-05T01:00:00Z"),
"length": 10.0,
"picture": Buffer.from([255, 255, 255, 255, 254]),
"species": "dangerous"
}
]
};
const serializedSawshark = client.serializer.serialize(mapper, sawshark, "result");
serializedSawshark.age.should.equal(22);
serializedSawshark["fish.type"].should.equal("sawshark");
serializedSawshark.siblings.length.should.equal(2);
serializedSawshark.siblings[0]["fish.type"].should.equal("shark");
serializedSawshark.siblings[0].age.should.equal(6);
serializedSawshark.siblings[0].birthday.should.equal(new Date("2012-01-05T01:00:00Z").toISOString());
serializedSawshark.siblings[1]["fish.type"].should.equal("sawshark");
serializedSawshark.siblings[1].age.should.equal(105);
serializedSawshark.siblings[1].birthday.should.equal(new Date("1900-01-05T01:00:00Z").toISOString());
serializedSawshark.siblings[1].picture.should.equal("//////4=");
serializedSawshark.picture.should.equal("//////4=");
done();
});

it("should deserialize headerCollectionPrefix", function () {
const mapper: msRest.CompositeMapper = {
serializedName: "something",
Expand Down
Empty file added xunit.xml
Empty file.

0 comments on commit 401b56e

Please sign in to comment.