This commit is contained in:
Rikki Gibson 2018-06-28 12:17:31 -07:00
Родитель 3653987335
Коммит 13da6db58b
2 изменённых файлов: 238 добавлений и 31 удалений

Просмотреть файл

@ -82,15 +82,30 @@ export class Serializer {
payload = [];
}
if (object == undefined) {
// Throw if required and object is null or undefined
if (mapper.required && !mapper.isConstant) {
throw new Error(`${objectName} cannot be null or undefined.`);
}
// Set Defaults
if (mapper.defaultValue != undefined || mapper.isConstant) {
object = mapper.defaultValue;
}
if (object == undefined && (mapper.defaultValue != undefined || mapper.isConstant)) {
object = mapper.defaultValue;
}
// This table of allowed values should help explain
// the mapper.required and mapper.nullable properties.
// X means "neither undefined or null are allowed".
// || required
// || true | false
// nullable || ==========================
// true || null | undefined/null
// false || X | undefined
// undefined || X | undefined/null
const { required, nullable } = mapper;
if (required && nullable && object === undefined) {
throw new Error(`${objectName} cannot be undefined.`);
}
if (required && !nullable && object == undefined) {
throw new Error(`${objectName} cannot be null or undefined.`);
}
if (!required && nullable === false && object === null) {
throw new Error(`${objectName} cannot be null.`);
}
if (object == undefined) {
@ -413,7 +428,7 @@ function serializeCompositeType(serializer: Serializer, mapper: CompositeMapper,
modelProperties: {}
}
};
if (object !== null && object !== undefined) {
if (object != undefined) {
let modelProps = mapper.type.modelProperties;
if (!modelProps) {
const className = mapper.type.className;
@ -450,33 +465,25 @@ function serializeCompositeType(serializer: Serializer, mapper: CompositeMapper,
for (const pathName of paths) {
const childObject = parentObject[pathName];
if ((childObject === null || childObject === undefined) && (object[key] !== null && object[key] !== undefined)) {
if ((childObject == undefined) && (object[key] != undefined)) {
parentObject[pathName] = {};
}
parentObject = parentObject[pathName];
}
}
// make sure required properties of the CompositeType are present
if (propertyMapper.required && !propertyMapper.isConstant) {
if (object[key] == undefined) {
throw new Error(`${key}" cannot be null or undefined in "${objectName}".`);
}
}
// make sure that readOnly properties are not sent on the wire
if (propertyMapper.readOnly) {
continue;
}
// serialize the property if it is present in the provided object instance
if (((parentObject !== null && parentObject !== undefined) && (propertyMapper.defaultValue !== null && propertyMapper.defaultValue !== undefined)) ||
(object[key] !== null && object[key] !== undefined)) {
if (parentObject != undefined) {
const propertyObjectName = propertyMapper.serializedName !== ""
? objectName + "." + propertyMapper.serializedName
: objectName;
const serializedValue = serializer.serialize(propertyMapper, object[key], propertyObjectName);
if (propName !== null && propName !== undefined) {
if (serializedValue !== undefined && propName != undefined) {
if (propertyMapper.xmlIsAttribute) {
// $ is the key attributes are kept under in xml2js.
// This keeps things simple while preventing name collision
@ -498,7 +505,6 @@ function serializeCompositeType(serializer: Serializer, mapper: CompositeMapper,
function deserializeCompositeType(serializer: Serializer, mapper: CompositeMapper, responseBody: any, objectName: string): any {
/*jshint validthis: true */
// check for polymorphic discriminator
if (mapper.type.polymorphicDiscriminator) {
mapper = getPolymorphicMapper(serializer, mapper, responseBody, objectName, "deserialize");
}
@ -578,7 +584,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 !== null && propertyInstance !== undefined) {
} else if (propertyInstance !== undefined) {
serializedValue = serializer.deserialize(propertyMapper, propertyInstance, propertyObjectName);
instance[key] = serializedValue;
}
@ -634,8 +640,8 @@ function getPolymorphicMapper(serializer: Serializer, mapper: CompositeMapper, o
// will be an object that contains the clientName (normalized property name, ex: "odatatype") and
// the serializedName (ex: "odata.type") (We do not escape the dots with double backslash in this case as it is not required)
// Thus when serializing, the user will give us an object which will contain the normalizedProperty hence we will lookup
// the clientName of the polmorphicDiscriminator in the mapper and during deserialization from the responseBody we will
// lookup the serializedName of the polmorphicDiscriminator in the mapper. This will help us in selecting the correct mapper
// the clientName of the polymorphicDiscriminator in the mapper and during deserialization from the responseBody we will
// lookup the serializedName of the polymorphicDiscriminator in the mapper. This will help us in selecting the correct mapper
// for the model that needs to be serializes or deserialized.
// We need this routing for backwards compatibility. This will absorb the breaking change in the mapper and allow new versions
// of the runtime to work seamlessly with older version (>= 0.17.0-Nightly20161008) of Autorest generated node.js clients.
@ -672,7 +678,7 @@ function getPolymorphicMapperObjectVersion(serializer: Serializer, mapper: Compo
if (object === null || object === undefined) {
throw new Error(`${objectName}" cannot be null or undefined. ` +
`"${discriminatorAsObject[polymorphicPropertyName]}" is the ` +
`polmorphicDiscriminator and is a required property.`);
`polymorphicDiscriminator is a required property.`);
}
if (object[discriminatorAsObject[polymorphicPropertyName]] === null ||
object[discriminatorAsObject[polymorphicPropertyName]] === undefined) {
@ -695,12 +701,12 @@ function getPolymorphicMapperObjectVersion(serializer: Serializer, mapper: Compo
function getPolymorphicMapperStringVersion(serializer: Serializer, mapper: CompositeMapper, object: any, objectName: string): CompositeMapper {
// check for polymorphic discriminator
const discriminatorAsString: string = mapper.type.polymorphicDiscriminator as string;
if (discriminatorAsString !== null && discriminatorAsString !== undefined) {
if (object === null || object === undefined) {
if (discriminatorAsString != undefined) {
if (object == undefined) {
throw new Error(`${objectName}" cannot be null or undefined. "${discriminatorAsString}" is the ` +
`polmorphicDiscriminator and is a required property.`);
`polymorphicDiscriminator is a required property.`);
}
if (object[discriminatorAsString] === null || object[discriminatorAsString] === undefined) {
if (object[discriminatorAsString] == undefined) {
throw new Error(`No discriminator field "${discriminatorAsString}" was found in "${objectName}".`);
}
let indexDiscriminator = undefined;
@ -743,6 +749,7 @@ export interface BaseMapper {
readOnly?: boolean;
isConstant?: boolean;
required?: boolean;
nullable?: boolean;
serializedName: string;
type: BaseMapperType;
defaultValue?: any;

Просмотреть файл

@ -588,6 +588,206 @@ describe("msrest", function () {
serializedPetGallery.pets[1].color.should.equal("red");
done();
});
it("should allow null when required: true and nullable: true", function() {
const mapper = {
required: false,
serializedName: 'testmodel',
type: {
name: 'Composite',
className: 'testmodel',
modelProperties: {
length: {
required: true,
nullable: true,
serializedName: 'length',
type: {
name: 'Number'
}
}
}
}
};
const result = Serializer.serialize(mapper, { length: null }, "testobj");
should.exist(result);
});
it("should not allow undefined when required: true and nullable: true", function() {
const mapper = {
required: false,
serializedName: 'testmodel',
type: {
name: 'Composite',
className: 'testmodel',
modelProperties: {
length: {
required: true,
nullable: true,
serializedName: 'length',
type: {
name: 'Number'
}
}
}
}
};
(function () { Serializer.serialize(mapper, { length: undefined }, "testobj"); }).should.throw("testobj.length cannot be undefined.");
});
it("should not allow null when required: true and nullable: false", function() {
const mapper = {
required: false,
serializedName: 'testmodel',
type: {
name: 'Composite',
className: 'testmodel',
modelProperties: {
length: {
required: true,
nullable: false,
serializedName: 'length',
type: {
name: 'Number'
}
}
}
}
};
(function () { Serializer.serialize(mapper, { length: null }, "testobj"); }).should.throw("testobj.length cannot be null or undefined.");
});
it("should not allow undefined when required: true and nullable: false", function() {
const mapper = {
required: false,
serializedName: 'testmodel',
type: {
name: 'Composite',
className: 'testmodel',
modelProperties: {
length: {
required: true,
nullable: false,
serializedName: 'length',
type: {
name: 'Number'
}
}
}
}
};
(function () { Serializer.serialize(mapper, { length: undefined }, "testobj"); }).should.throw("testobj.length cannot be null or undefined.");
});
it("should not allow null when required: true and nullable is undefined", function() {
const mapper = {
serializedName: "foo",
required: true,
type: {
name: "String"
}
};
(function () { Serializer.serialize(mapper, null, "testobj"); }).should.throw("testobj cannot be null or undefined.");
});
it("should not allow undefined when required: true and nullable is undefined", function() {
const mapper = {
serializedName: "foo",
required: true,
type: {
name: "String"
}
};
(function () { Serializer.serialize(mapper, undefined, "testobj"); }).should.throw("testobj cannot be null or undefined.");
});
it("should allow null when required: false and nullable: true", function() {
const mapper = {
serializedName: "foo",
required: false,
nullable: true,
type: {
name: "String"
}
};
Serializer.serialize(mapper, null, "testobj");
});
it("should not allow null when required: false and nullable: false", function() {
const mapper = {
serializedName: "foo",
required: false,
nullable: false,
type: {
name: "String"
}
};
(function () { Serializer.serialize(mapper, null, "testobj"); }).should.throw("testobj cannot be null.");
});
it("should allow null when required: false and nullable is undefined", function() {
const mapper = {
serializedName: "foo",
required: false,
type: {
name: "String"
}
};
Serializer.serialize(mapper, null, "testobj");
});
it("should allow undefined when required: false and nullable: true", function() {
const mapper = {
serializedName: "foo",
required: false,
nullable: true,
type: {
name: "String"
}
};
Serializer.serialize(mapper, undefined, "testobj");
});
it("should allow undefined when required: false and nullable: false", function() {
const mapper = {
serializedName: "fooType",
type: {
name: "Composite",
className: "fooType",
modelProperties: {
length: {
serializedName: "length",
required: false,
nullable: false,
type: {
name: "String"
}
}
}
}
};
Serializer.serialize(mapper, { length: undefined }, "testobj");
});
it("should allow undefined when required: false and nullable is undefined", function() {
const mapper = {
serializedName: "foo",
required: false,
type: {
name: "String"
}
};
Serializer.serialize(mapper, undefined, "testobj");
});
});
describe("deserialize", function () {