@venly/venly-core-sdk
Version:
Javascrip/Typescript SDK for Venly's Web3 Services
1,066 lines • 48.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.JsonConvert = exports.JsonConvertSettings = void 0;
const any_1 = require("./any");
const json_convert_enums_1 = require("./json-convert-enums");
const json_convert_options_1 = require("./json-convert-options");
class JsonConvertSettings {
constructor() {
/**
* Determines how the JsonConvert class instance should operate.
*
* You may assign three different values:
* - OperationMode.DISABLE: json2typescript will be disabled, no type checking or mapping is done
* - OperationMode.ENABLE: json2typescript is enabled, but only errors are logged
* - OperationMode.LOGGING: json2typescript is enabled and detailed information is logged
*/
this.operationMode = json_convert_enums_1.OperationMode.ENABLE;
/**
* Determines which types are allowed to be null.
* This setting may be overridden by property settings (see PropertyConvertingMode).
*
* You may assign three different values:
* - ValueCheckingMode.ALLOW_NULL: all given values are allowed to be null
* - ValueCheckingMode.ALLOW_OBJECT_NULL: objects are allowed to be null, primitive types are not allowed to be null
* - ValueCheckingMode.DISALLOW_NULL: no null values are tolerated
*/
this.valueCheckingMode = json_convert_enums_1.ValueCheckingMode.ALLOW_NULL;
this.deserialize_skipNullValues = true;
this.serialize_skipNullValues = true;
/**
* Determines whether primitive types should be checked.
* If true, it will be allowed to assign primitive to other primitive types.
*/
this.ignorePrimitiveChecks = true;
this.warnIfKeyNotFound = false;
/**
* Determines the rule of how JSON properties shall be matched with class properties during deserialization.
*
* You may assign the following values:
* - PropertyMatchingRule.CASE_STRICT: JSON properties need to match exactly the names in the decorators
* - PropertyMatchingRule.CASE_INSENSITIVE: JSON properties need to match names in the decorators, but names they
* are not case sensitive
*/
this.propertyMatchingRule = json_convert_enums_1.PropertyMatchingRule.CASE_STRICT;
/**
* Determines how nullable property types should be serialized and deserialized.
* Nullable types are either missing (in JSON), undefined (in TypeScript) or null (both).
*
* If the propertyConvertingMode has a non-undefined value, it overrides the individual settings of every property.
*
* The values should be used as follows:
* Determines how nullable property types should be serialized and deserialized.
* Nullable types are either missing (in JSON), undefined (in TypeScript) or null (both).
*
* If the propertyConvertingMode has a non-undefined value, it overrides the individual settings of every property.
*
* The values should be used as follows:
* - MAP_NULLABLE: the mapper is applied, type is checked
* - IGNORE_NULLABLE: the mapper is not applied if the property is missing, undefined or null; the property is
* not added to the result
* - PASS_NULLABLE: the mapper is not applied if the property is missing, undefined or null; the property is
* added with its value to the result
*/
this.propertyConvertingMode = undefined;
}
}
exports.JsonConvertSettings = JsonConvertSettings;
/**
* Offers a simple API for mapping JSON objects to TypeScript/JavaScript classes and vice versa.
*
* @see https://www.npmjs.com/package/json2typescript full documentation on NPM
*/
class JsonConvert {
////////////////////
// PUBLIC METHODS //
////////////////////
static addGlobalConverter(targetType, converterType) {
var _a;
if (!this._isJsonConverter(converterType))
throw new Error(`Failed to add global converter \'${(_a = converterType.name) !== null && _a !== void 0 ? _a : converterType}\'. Invalid Converter Type, make sure the class is marked with @JsonConverter`);
this._globalConverters.set(targetType, converterType);
}
static removeGlobalConverter(targetType) {
return this._globalConverters.delete(targetType);
}
static _getConverter(target) {
var convType = null;
if (target instanceof json_convert_options_1.JsonPropertyMap) {
convType = target.converterType;
if (convType == null) {
convType = this._globalConverters.get(target.propertyType);
}
}
else {
convType = Reflect.getOwnMetadata(json_convert_options_1.JsonMetaKeys.ConverterType, target);
if (convType == null) {
convType = this._globalConverters.get(target);
}
}
if (convType == null)
return null;
var convKey = Reflect.getOwnMetadata(json_convert_options_1.JsonMetaKeys.ConverterKey, convType);
if (convKey == null) {
var objName = undefined;
if (convType.name != null)
objName = convType.name;
else if (convType.prototype != null)
objName = convType.prototype.constructor.name;
console.warn(`\'${objName}\' is not a valid converter! Make sure to mark the class with the @JsonConverter decorator.`);
return null;
}
if (this._converterCache.has(convKey)) {
return this._converterCache.get(convKey);
}
var conv = new convType();
this._converterCache.set(convKey, conv);
return conv;
}
// private static _getConverter(target : Object, propertyKey : string | null = null)
// {
// var convType = undefined;
// if(propertyKey != null) convType = Reflect.getMetadata(JsonMetaKeys.ConverterType, target, propertyKey);
// else convType = Reflect.getOwnMetadata(JsonMetaKeys.ConverterType, target);
// if(convType == null){
// return null;
// }
// var convKey = Reflect.getOwnMetadata(JsonMetaKeys.ConverterKey, convType);
// if(convKey == null){
// var objName = undefined;
// if(convType.name != null) objName = convType.name;
// else if(convType.prototype != null) objName = convType.prototype.constructor.name;
// console.warn(`\'${objName}\' is not a valid converter! Make sure to mark the class with the @JsonConverter decorator.`)
// return null;
// }
// if(this._converterCache.has(convKey)){
// return this._converterCache.get(convKey);
// }
// var conv = new convType();
// this._converterCache.set(convKey, conv);
// return conv;
// }
static _getObjectProps(target) {
var targetProps = Reflect.getMetadata(json_convert_options_1.JsonMetaKeys.ClassProps, target);
var base = Object.getPrototypeOf(target);
if (base == null) {
return targetProps;
}
var baseProps = this._getObjectProps(base);
if (baseProps == null)
return targetProps;
return new Map([...baseProps.entries(), ...targetProps.entries()]);
}
static _getPropertyMap(props, propertyName, fromJson = false) {
if (props == null)
return null;
if (propertyName == null)
return null;
if (props.has(propertyName))
return props.get(propertyName);
if (!fromJson)
return null;
props.forEach(map => {
if (map.jsonName == propertyName)
return map;
});
return null;
}
/**
* Tries to serialize a TypeScript object or array of objects to JSON using the mappings defined on
* the specified class reference. Note that if a class reference is provided, it will be used as
* the source of property mapping for serialization, even if the object or one of its elements is
* an instance of a different class with its own mappings. Also, ONLY the properties from the
* class reference will be serialized - any additional properties on the object(s) will be silently
* ignored.
*
* @param data object or array of objects
* @param classReference the class reference which provides the property mappings to use
*
* @returns the JSON object
*
* @throws an Error in case of failure
*
* @see https://www.npmjs.com/package/json2typescript full documentation
*/
static serialize(data, classReference, settings = null) {
if (settings == null)
settings = this._defaultSettings;
if (settings.operationMode === json_convert_enums_1.OperationMode.DISABLE) {
return null;
}
// Call the appropriate method depending on the type
if (data instanceof Array) {
return JSON.stringify(this.serializeArray(data, classReference, settings));
}
else if (typeof data === "object") { // careful: an array is an object in TypeScript!
return JSON.stringify(this.serializeObject(data, classReference, settings));
}
else {
throw new Error("Fatal error in JsonConvert. " +
"Passed parameter data in JsonConvert.serialize() is not in valid format (object or array)." +
"\n");
}
}
/**
* Tries to serialize a TypeScript object to a JSON object using either the mappings on the
* provided class reference, if present, or on the provided object. Note that if a class
* reference is provided, it will be used as the source of property mapping for serialization,
* even if the object is itself an instance of a different class with its own mappings.
* Also, ONLY the properties from the class reference will be serialized - any additional
* properties on the object will be silently ignored.
*
* @param data object containing the values to be mapped to a JSON object, must be an
* instance of a class with JSON mappings if no class reference is provided
* @param classReference optional class reference which provides the property mappings to use
*
* @returns the JSON object
*
* @throws an Error in case of failure
*
* @see https://www.npmjs.com/package/json2typescript full documentation
*/
static serializeObject(data, classReference, settings = null, ignoreConverter = false) {
if (settings == null)
settings = this._defaultSettings;
if (settings.operationMode === json_convert_enums_1.OperationMode.DISABLE) {
return data;
}
//data = this.mapUndefinedToNull && data === undefined ? null as any : data;
// Check if the passed type is allowed
if (data === undefined) {
throw new Error("Fatal error in JsonConvert. " +
"Passed parameter instance in JsonConvert.serializeObject() is undefined. This is not a valid JSON format." +
"\n");
}
else if (data === null) {
if (settings.valueCheckingMode === json_convert_enums_1.ValueCheckingMode.DISALLOW_NULL) {
throw new Error("Fatal error in JsonConvert. " +
"Passed parameter instance in JsonConvert.serializeObject() is null. You have specified to " +
"disallow null values." +
"\n");
}
else {
return data;
}
}
else if (typeof (data) !== "object" || data instanceof Array) {
throw new Error("Fatal error in JsonConvert. " +
"Passed parameter instance in JsonConvert.serializeObject() is not of type object." +
"\n");
}
// Now serialize and return the plain object
if (settings.operationMode === json_convert_enums_1.OperationMode.LOGGING) {
console.log("----------");
console.log("Receiving JavaScript instance:");
console.log(data);
}
//Check for converter
if (!ignoreConverter && data != null) {
var converter = this._getConverter(data);
if (converter != null) {
if (converter.CanSerialize) {
return converter.serialize(data, settings);
}
}
}
let jsonObject = {};
let instance;
if (!!classReference) {
instance = new classReference();
}
else {
instance = data;
}
var props = this._getObjectProps(instance);
props.forEach((value, key) => {
try {
this._serializeObject_loopProperty(data, instance, value, jsonObject, settings);
}
catch (ex) {
if (settings.operationMode === json_convert_enums_1.OperationMode.LOGGING) {
console.log("Failed to serialize property:");
console.log(ex);
console.log("----------");
}
throw ex;
}
});
// // Loop through all initialized class properties on the mapping instance
// for (const propertyKey of Object.keys(instance)) {
// try {
// this._serializeObject_loopProperty(data, instance, propertyKey, jsonObject, settings);
// } catch (ex) {
// if (settings.operationMode === OperationMode.LOGGING) {
// console.log("Failed to serialize property:");
// console.log(ex);
// console.log("----------");
// }
// throw ex;
// }
// }
if (settings.operationMode === json_convert_enums_1.OperationMode.LOGGING) {
console.log("Returning JSON object:");
console.log(jsonObject);
console.log("----------");
}
return jsonObject;
}
/**
* Tries to serialize a TypeScript array to a JSON array using either the mappings on the
* provided class reference, if present, or on the provided object. Note that if a class
* reference is provided, ALL objects in the array will be serialized using the mappings
* from that class reference, even if they're actually instances of a different class.
* Also, ONLY the properties from the class reference will be serialized - any additional
* properties on the objects will be silently ignored.
*
* @param dataArray array of objects containing the values to be mapped to a JSON object, which
* must be instances of classes with JSON mappings if no class reference is provided
* @param classReference optional class reference which provides the property mappings to use
*
* @returns the JSON array
*
* @throws an Error in case of failure
*
* @see https://www.npmjs.com/package/json2typescript full documentation
*/
static serializeArray(dataArray, classReference, settings = null) {
if (settings == null)
settings = this._defaultSettings;
if (settings.operationMode === json_convert_enums_1.OperationMode.DISABLE) {
return dataArray;
}
//dataArray = this.mapUndefinedToNull && dataArray === undefined ? null as any : dataArray;
// Check if the passed type is allowed
if (dataArray === undefined) {
throw new Error("Fatal error in JsonConvert. " +
"Passed parameter instanceArray in JsonConvert.serializeArray() is undefined. This is not a valid JSON format." +
"\n");
}
else if (dataArray === null) {
if (settings.valueCheckingMode === json_convert_enums_1.ValueCheckingMode.DISALLOW_NULL) {
throw new Error("Fatal error in JsonConvert. " +
"Passed parameter instanceArray in JsonConvert.serializeArray() is null. You have specified to " +
"disallow null values." +
"\n");
}
else {
return dataArray;
}
}
else if (typeof (dataArray) !== "object" || dataArray instanceof Array === false) {
throw new Error("Fatal error in JsonConvert. " +
"Passed parameter instanceArray in JsonConvert.serializeArray() is not of type array." +
"\n");
}
// Now serialize and return the plain object
if (settings.operationMode === json_convert_enums_1.OperationMode.LOGGING) {
console.log("----------");
console.log("Receiving JavaScript array:");
console.log(dataArray);
}
let jsonArray = [];
// Loop through all array elements
for (const dataObject of dataArray) {
jsonArray.push(this.serializeObject(dataObject, classReference, settings));
}
if (settings.operationMode === json_convert_enums_1.OperationMode.LOGGING) {
console.log("Returning JSON array:");
console.log(jsonArray);
console.log("----------");
}
return jsonArray;
}
/**
* Tries to deserialize given JSON to a TypeScript object or array of objects.
*
* @param json the JSON as object or array
* @param classReference the class reference
*
* @returns the deserialized data (TypeScript instance or array of TypeScript instances)
*
* @throws an Error in case of failure
*
* @see https://www.npmjs.com/package/json2typescript full documentation
*/
static deserialize(json, classReference = null, settings = null) {
if (settings == null)
settings = this._defaultSettings;
if (settings.operationMode === json_convert_enums_1.OperationMode.DISABLE) {
return json;
}
// Call the appropriate method depending on the type
if (Array.isArray(json)) {
return this.deserializeArray(json, classReference, settings);
}
else if (typeof json === "object") { // careful: an array is an object in TypeScript!
return this.deserializeObject(json, classReference, settings);
}
else {
throw new Error("Fatal error in JsonConvert. " +
"Passed parameter json in JsonConvert.deserialize() is not in valid JSON format (object or array)." +
"\n");
}
}
/**
* Tries to deserialize a JSON object to a TypeScript object.
*
* @param jsonObject the JSON object
* @param classReference the class reference
*
* @returns the deserialized TypeScript instance
*
* @throws an Error in case of failure
*
* @see https://www.npmjs.com/package/json2typescript full documentation
*/
static deserializeObject(jsonObject, classReference = null, settings = null, ignoreConverter = false) {
if (settings == null)
settings = this._defaultSettings;
if (settings.operationMode === json_convert_enums_1.OperationMode.DISABLE) {
return jsonObject;
}
if (!ignoreConverter && classReference != null) {
var converter = this._getConverter(classReference);
if (converter != null && converter.CanDeserialize) {
return converter.deserialize(jsonObject, classReference, settings);
}
}
const realClassReference = this._getRealClassReference(jsonObject, classReference);
//todo...
//jsonObject = this.mapUndefinedToNull && jsonObject === undefined ? null as any : jsonObject;
// Check if the passed type is allowed
if (jsonObject === undefined) {
throw new Error("Fatal error in JsonConvert. " +
"Passed parameter jsonObject in JsonConvert.deserializeObject() is undefined. This is not a valid JSON format." +
"\n");
}
else if (jsonObject === null) {
if (settings.valueCheckingMode === json_convert_enums_1.ValueCheckingMode.DISALLOW_NULL) {
throw new Error("Fatal error in JsonConvert. " +
"Passed parameter jsonObject in JsonConvert.deserializeObject() is null. You have specified to " +
"disallow null values." +
"\n");
}
else {
return jsonObject;
}
}
else if (typeof (jsonObject) !== "object" || jsonObject instanceof Array) {
if (classReference != null
&& classReference.name != null
&& classReference.name == "Any") {
return jsonObject;
}
throw new Error("Fatal error in JsonConvert. " +
"Passed parameter jsonObject in JsonConvert.deserializeObject() is not of type object." +
"\n");
}
// Now deserialize and return the instance
if (settings.operationMode === json_convert_enums_1.OperationMode.LOGGING) {
console.log("----------");
console.log("Receiving JSON object:");
console.log(jsonObject);
}
let instance = new realClassReference();
var props = this._getObjectProps(instance);
props.forEach((value, key) => {
try {
this._deserializeObject_loopProperty(instance, value, jsonObject, settings);
}
catch (ex) {
if (settings.operationMode === json_convert_enums_1.OperationMode.LOGGING) {
console.log("Failed to deserialize property:");
console.log(ex);
console.log("----------");
}
throw ex;
}
});
// // Loop through all initialized class properties
// for (const propertyKey in instance) {
// try {
// this._deserializeObject_loopProperty(instance, propertyKey, jsonObject, settings);
// } catch (ex) {
// if (settings.operationMode === OperationMode.LOGGING) {
// console.log("Failed to deserialize property:");
// console.log(ex);
// console.log("----------");
// }
// throw ex;
// }
// }
if (settings.operationMode === json_convert_enums_1.OperationMode.LOGGING) {
console.log("Returning CLASS instance:");
console.log(instance);
console.log("----------");
}
return instance;
}
/**
* Tries to deserialize a JSON array to a TypeScript array.
*
* @param jsonArray the JSON array
* @param classReference the object class
*
* @returns the deserialized array of TypeScript instances
*
* @throws an Error in case of failure
*
* @see https://www.npmjs.com/package/json2typescript full documentation
*/
static deserializeArray(jsonArray, classReference = null, settings = null) {
if (settings == null)
settings = this._defaultSettings;
if (settings.operationMode === json_convert_enums_1.OperationMode.DISABLE) {
return jsonArray;
}
//todo: fix
//jsonArray = this.mapUndefinedToNull && jsonArray === undefined ? null as any : jsonArray;
// Check if the passed type is allowed
if (jsonArray === undefined) {
throw new Error("Fatal error in JsonConvert. " +
"Passed parameter jsonArray in JsonConvert.deserializeObject() is undefined. This is not a valid JSON format." +
"\n");
}
else if (jsonArray === null) {
if (settings.valueCheckingMode === json_convert_enums_1.ValueCheckingMode.DISALLOW_NULL) {
throw new Error("Fatal error in JsonConvert. " +
"Passed parameter jsonArray in JsonConvert.deserializeObject() is null. You have specified to " +
"disallow null values." +
"\n");
}
else {
return jsonArray;
}
}
else if (typeof (jsonArray) !== "object" || Array.isArray(jsonArray) === false) {
throw new Error("Fatal error in JsonConvert. " +
"Passed parameter jsonArray in JsonConvert.deserializeArray() is not of type array." +
"\n");
}
// Now deserialize and return the array
if (settings.operationMode === json_convert_enums_1.OperationMode.LOGGING) {
console.log("----------");
console.log("Receiving JSON array:");
console.log(jsonArray);
}
let array = [];
// Loop through all array elements
for (const jsonObject of jsonArray) {
array.push(this.deserializeObject(jsonObject, classReference));
}
if (settings.operationMode === json_convert_enums_1.OperationMode.LOGGING) {
console.log("Returning array of CLASS instances:");
console.log(array);
console.log("----------");
}
return array;
}
/////////////////////
// PRIVATE METHODS //
/////////////////////
/**
* Returns the correct class reference for the provided JSON object.
* If the provided class reference is null, the class reference is retrieved from the class map using the discriminator property.
*
* @param jsonObject the JSON object
* @param classReference the class reference
* @throws throws an Error in case of failure
*/
static _getRealClassReference(jsonObject, classReference) {
// Make sure the class reference is given for if the discriminator is disabled
if (classReference === null) {
throw new Error("Fatal error in JsonConvert. " +
"Passed parameter classReference in JsonConvert.deserialize() is null. " +
"This is only allowed if discriminator feature is enabled." +
"\n");
}
return classReference;
}
/**
* Tries to find the JSON mapping for a given class property from the given instance used for mapping,
* and finally assign the value from the given dataObject
*
* @param dataObject the object containing the value to be assigned
* @param instance the instance of the class used for mapping
* @param classPropertyName the property name
* @param json the JSON object
* @throws throws an Error in case of failure
*/
static _serializeObject_loopProperty(dataObject, instance, propMap, json, settings = null) {
var _a;
if (settings == null)
settings = this._defaultSettings;
// var jsonInclude = Reflect.getMetadata(JsonMetaKeys.Include, instance, classPropertyName);
// if(!jsonInclude) return;
var jsonPropName = propMap.jsonName;
//if(jsonPropName == null) jsonPropName = classPropertyName;
var jsonPropType = propMap.propertyType;
var convertingMode = (_a = settings.propertyConvertingMode) !== null && _a !== void 0 ? _a : json_convert_enums_1.PropertyConvertingMode.PASS_NULLABLE;
//Converter?
var converter = this._getConverter(propMap);
if (converter != null && converter.CanSerialize) {
json[jsonPropName] = converter.serialize(dataObject[propMap.propertyName], settings);
return;
}
//Default Mapping
let classInstancePropertyValue = dataObject[propMap.propertyName];
if (classInstancePropertyValue == null && settings.serialize_skipNullValues)
return;
// Check if we have a nullable type
//todo: fix
//classInstancePropertyValue = this.mapUndefinedToNull && classInstancePropertyValue === undefined ? null : classInstancePropertyValue;
if (classInstancePropertyValue === undefined || classInstancePropertyValue === null) {
if (convertingMode === json_convert_enums_1.PropertyConvertingMode.IGNORE_NULLABLE) {
return;
}
if (convertingMode === json_convert_enums_1.PropertyConvertingMode.PASS_NULLABLE) {
json[jsonPropName] = classInstancePropertyValue;
return;
}
}
json[jsonPropName] = this._convertProperty(jsonPropType, classInstancePropertyValue, settings, true);
// // Map the property
// try {
// json[jsonPropertyName] = customConverter !== null ?
// customConverter.serialize(classInstancePropertyValue) :
// this.convertProperty(expectedJsonType, classInstancePropertyValue, convertingMode, true);
// const classConstructorName = dataObject?.constructor?.name;
// if (this._useDiscriminator && json instanceof Object) {
// this.classes.forEach((classDataObject: {new(): any}, key: string) => {
// if (classDataObject.name === classConstructorName) {
// json[this._discriminatorPropertyName] = key;
// }
// });
// }
// } catch (e : any) {
// throw new Error(
// "Fatal error in JsonConvert. " +
// "Failed to map the JavaScript instance of class \"" + instance[Settings.CLASS_IDENTIFIER] + "\" to JSON because of a type error.\n\n" +
// "\tClass property: \n\t\t" + classPropertyName + "\n\n" +
// "\tClass property value: \n\t\t" + classInstancePropertyValue + "\n\n" +
// "\tExpected type: \n\t\t" + this.getExpectedType(expectedJsonType) + "\n\n" +
// "\tRuntime type: \n\t\t" + this.getTrueType(classInstancePropertyValue) + "\n\n" +
// "\tJSON property: \n\t\t" + jsonPropertyName + "\n\n" +
// e.message + "\n"
// );
// }
}
/**
* Tries to find the JSON mapping for a given class property and finally assign the value.
*
* @param instance the instance of the class
* @param classPropertyName the property name
* @param json the JSON object
*
* @throws throws an Error in case of failure
*/
static _deserializeObject_loopProperty(instance, propMap, json, settings = null) {
var _a;
if (settings == null)
settings = this._defaultSettings;
// var jsonInclude = Reflect.getMetadata(JsonMetaKeys.Include, instance, classPropertyName);
// if(!jsonInclude) return;
var jsonPropName = propMap.jsonName;
//if(jsonPropName == null) jsonPropName = classPropertyName;
var jsonPropType = propMap.propertyType;
var convertingMode = (_a = settings.propertyConvertingMode) !== null && _a !== void 0 ? _a : json_convert_enums_1.PropertyConvertingMode.PASS_NULLABLE;
// // Get expected and real values
// const jsonPropertyName: string = mappingOptions.jsonPropertyName;
// let expectedJsonType: any = mappingOptions.expectedJsonType;
// const convertingMode: PropertyConvertingMode = this.propertyConvertingMode ?? mappingOptions.convertingMode;
// const customConverter: any = mappingOptions.customConverter;
if (!(jsonPropName in json)) {
if (settings.warnIfKeyNotFound)
console.warn(`Key=${jsonPropName} not found`);
return;
}
var jsonValue = json[jsonPropName];
//Handle Value==NULL
if (jsonValue == null) {
if (convertingMode == json_convert_enums_1.PropertyConvertingMode.PASS_NULLABLE) {
instance[propMap.propertyName] = jsonValue;
}
return;
}
//Default Mapping
instance[propMap.propertyName] = this._convertProperty(jsonPropType, jsonValue, settings);
// let jsonValue: any = undefined;
// try {
// jsonValue = this.getObjectValue(json, jsonPropName);
// } catch {}
// // Check if we have a nullable type
// jsonValue = this.mapUndefinedToNull && jsonValue === undefined ? null : jsonValue;
// if (jsonValue === undefined || jsonValue === null) {
// if (convertingMode === PropertyConvertingMode.IGNORE_NULLABLE) {
// return;
// }
// if (convertingMode === PropertyConvertingMode.PASS_NULLABLE) {
// instance[classPropertyName] = jsonValue;
// return;
// }
// }
// // Map the property
// try {
// const classConstructorName = jsonValue instanceof Object ? jsonValue[this.discriminatorPropertyName] : null;
// if (this._useDiscriminator && this.classes.has(classConstructorName)) {
// expectedJsonType = this.classes.get(classConstructorName);
// }
// instance[classPropertyName] = customConverter !== null ?
// customConverter.deserialize(jsonValue) :
// this.convertProperty(expectedJsonType, jsonValue, convertingMode);
// } catch (e : any) {
// throw new Error(
// "Fatal error in JsonConvert. " +
// "Failed to map the JSON object to the class \"" + instance[Settings.CLASS_IDENTIFIER] + "\" because of a type error.\n\n" +
// "\tClass property: \n\t\t" + classPropertyName + "\n\n" +
// "\tExpected type: \n\t\t" + this.getExpectedType(expectedJsonType) + "\n\n" +
// "\tJSON property: \n\t\t" + jsonPropertyName + "\n\n" +
// "\tJSON type: \n\t\t" + this.getJsonType(jsonValue) + "\n\n" +
// "\tJSON value: \n\t\t" + JSON.stringify(jsonValue) + "\n\n" +
// e.message + "\n"
// );
// }
}
static _isAnyType(targetType) {
if (targetType == null)
return false;
if (targetType.name == null)
return false;
if (targetType.name == 'Any')
return true;
return false;
}
////////////////////
// HELPER METHODS //
////////////////////
/**
* Compares the type of a given value with an internal expected json type.
* Either returns the resulting value or throws an exception.
*
* @param expectedType the expected type for the property
* @param value the property value to verify
* @param convertingMode the converting mode for this property
* @param serialize optional param (default: false), if given, we are in serialization mode
*
* @returns returns the resulted mapped property
*
* @throws an error in case of failure
*/
static _convertProperty(expectedType, value, settings = null, serialize) {
if (settings == null)
settings = this._defaultSettings;
var propertyConvertingMode = settings.propertyConvertingMode || json_convert_enums_1.PropertyConvertingMode.PASS_NULLABLE;
////////////////////////////
// Prior checks and setup //
////////////////////////////
// Return the value immediately if we don't care about the type
// if (expectedType == null || expectedType instanceof Object || expectedType instanceof Any) {
// return value;
// }
if (expectedType == null || this._isAnyType(expectedType)) {
return value;
}
if (!(Array.isArray(value))) {
//Converter?
var converter = this._getConverter(expectedType);
if (converter != null) {
if (serialize && converter.CanSerialize) {
return converter.serialize(value, settings);
}
else if (!serialize && converter.CanDeserialize) {
return converter.deserialize(value, expectedType, settings);
}
}
}
// Check if we have a nullable type
//todo: fix
//value = this.mapUndefinedToNull && value === undefined ? null : value;
if (value === undefined || value === null) {
if (propertyConvertingMode === json_convert_enums_1.PropertyConvertingMode.IGNORE_NULLABLE) {
return undefined;
}
if (propertyConvertingMode === json_convert_enums_1.PropertyConvertingMode.PASS_NULLABLE) {
return value;
}
}
let expectedDimension = "1";
if (expectedType instanceof Array) {
expectedDimension = "2";
}
let valueDimension = "1or2";
if (Array.isArray(value)) {
valueDimension = "2";
}
else if (!(value instanceof Object)) {
valueDimension = "1";
}
if (expectedDimension === "1" && valueDimension === "2") {
throw new Error("\tReason: Expected a non-array type, but given value is an array.");
}
if (expectedDimension === "2" && valueDimension === "1") {
// Allow to use null in the special case
if (value === null && settings.valueCheckingMode !== json_convert_enums_1.ValueCheckingMode.DISALLOW_NULL) {
return null;
}
else if (value === null) {
throw new Error("\tReason: Expected an array, but given value is null.");
}
throw new Error(`\tReason: Expected an array, but given value is a primitive type. (value=${JSON.stringify(value)})`);
}
//////////////////
// Check values //
//////////////////
if (expectedDimension === "2" && (valueDimension === "2" || valueDimension === "1or2")) {
// Return an empty array if we have an empty array or object as value
if (value.length === 0 || Object.keys(value).length === 0) {
return [];
}
// Return the value if we don't care about the array type
if (expectedType.length === 0) {
return value;
}
// Copy the expectedJsonType array so we don't change the class-level mapping based on the value of this property
const jsonType = expectedType.slice(0);
const array = [];
if (valueDimension === "2") {
// Loop through the data. Both type and value are at least of length 1
let autofillType = jsonType.length < value.length;
for (let i = 0; i < value.length; i++) {
if (autofillType && i >= jsonType.length) {
jsonType[i] = jsonType[i - 1];
}
array[i] = this._convertProperty(jsonType[i], value[i], settings, serialize);
}
return array;
}
else {
// Loop through the data. Both type and value are at least of length 1
let autofillType = jsonType.length < Object.keys(value).length;
let i = 0;
for (let key in value) {
if (autofillType && i >= jsonType.length) {
jsonType[i] = jsonType[i - 1];
}
array[key] = this._convertProperty(jsonType[i], value[key], settings, serialize);
i++;
}
return array;
}
}
else if (expectedDimension === "1" && (valueDimension === "1" || valueDimension === "1or2")) {
if (this._isJsonObject(expectedType)) {
return serialize ?
this.serializeObject(value, expectedType) :
this.deserializeObject(value, expectedType);
}
// Check if objects match
else if (((expectedType instanceof Object && [String, Number, Boolean].includes(expectedType) === false) || typeof expectedType === "string") && value instanceof Object) {
// If the expected type is a string (means: lazy-loading), get the real type from the registered classes
if (typeof expectedType === "string") {
//const realExpectedType = this.classes.get(expectedType);
//if (!realExpectedType) {
throw new Error("\tReason: Given expected type \"" + expectedType + "\" not registered with JsonConvert.registerClasses().");
//}
//expectedType = realExpectedType;
}
}
else {
// Check for null values
if (value === null) {
if (expectedType === String || expectedType === Number || expectedType === Boolean) {
if (settings.valueCheckingMode === json_convert_enums_1.ValueCheckingMode.ALLOW_NULL) {
return null;
}
else {
throw new Error("\tReason: Given value null does not match the expected primitive type.");
}
}
else {
if (settings.valueCheckingMode !== json_convert_enums_1.ValueCheckingMode.DISALLOW_NULL) {
return null;
}
else {
throw new Error("\tReason: Given value null does not match the expected object type.");
}
}
}
// Check for primitive matches
if ((expectedType === String && typeof (value) === "string") ||
(expectedType === Number && typeof (value) === "number") ||
(expectedType === Boolean && typeof (value) === "boolean") ||
(expectedType === Date)) {
return value;
}
else {
if (settings.ignorePrimitiveChecks && ["string", "number", "boolean"].includes(typeof (value))) {
return value;
}
throw new Error("\tReason: Given value type does not match the expected primitive type.");
}
}
}
// All other attempts are fatal
throw new Error("\tReason: Mapping failed because of an unknown error.");
}
static _isJsonObject(target) {
return Reflect.hasOwnMetadata(json_convert_options_1.JsonMetaKeys.ClassName, target);
}
static _isJsonConverter(target) {
return Reflect.hasOwnMetadata(json_convert_options_1.JsonMetaKeys.ConverterKey, target);
}
/**
* Gets the value of an object for a given value.
* If the object does not have the specific key, an Error is thrown.
*
* @param data
* @param key
*
* @returns returns the value
*
* @throws an Error in case of the key was not found in the object
*/
static _getObjectValue(data, key, settings = null) {
if (settings == null)
settings = this._defaultSettings;
// If we do not care about the case of the key, ad
if (settings.propertyMatchingRule === json_convert_enums_1.PropertyMatchingRule.CASE_INSENSITIVE) {
// Create a mapping of the keys: keys[lowercase]=normalcase
const keyMapping = Object.keys(data).reduce((keys, key) => {
keys[key.toLowerCase()] = key;
return keys;
}, {});
// Define the new key
key = keyMapping[key.toLowerCase()];
}
// Throw an error if the key is not in the object
if (key in data === false) {
throw new Error();
}
return data[key];
}
///////////////////////////
// JSON2TYPESCRIPT TYPES //
///////////////////////////
/**
* Returns a string representation of the expected json type.
*
* @param expectedJsonType the expected type given from the decorator
*
* @returns {string} the string representation
*/
static _getExpectedType(expectedJsonType) {
let type = "";
if (expectedJsonType instanceof Array) {
type = "[";
for (let i = 0; i < expectedJsonType.length; i++) {
if (i > 0)
type += ",";
type += this._getExpectedType(expectedJsonType[i]);
}
type += "]";
return type;
}
else {
if (expectedJsonType === any_1.Any || expectedJsonType === null || expectedJsonType === Object) {
return "any";
}
else if (expectedJsonType === String || expectedJsonType === Boolean || expectedJsonType === Number) {
return (new expectedJsonType()).constructor.name.toLowerCase();
}
else if (typeof expectedJsonType === "function") {
return (new expectedJsonType()).constructor.name;
}
else if (typeof expectedJsonType === "string") {
return expectedJsonType;
}
else if (expectedJsonType === undefined) {
return "undefined";
}
else {
return "?????";
}
}
}
/**
* Returns a string representation of the JSON value type.
*
* @param jsonValue the JSON value
*
* @returns {string} the string representation
*/
static _getJsonType(jsonValue) {
if (jsonValue === null)
return "null";
let type = "";
if (jsonValue instanceof Array) {
type = "[";
for (let i = 0; i < jsonValue.length; i++) {
if (i > 0)
type += ",";
type += this._getJsonType(jsonValue[i]);
}
type += "]";
return type;
}
else {
return typeof (jsonValue);
}
}
/**
* Returns a string representation of the true TypeScript type.
*
* @param trueValue the true value
*
* @returns {string} the string representation
*/
static _getTrueType(trueValue) {
return typeof (trueValue);
}
}
exports.JsonConvert = JsonConvert;
////////////////
// PROPERTIES //
////////////////
// /**
// * Determines whether a missing or undefined property value should be considered as null or not.
// *
// * If true, a missing JSON value will be added and set as null before deserialization.
// * For serialization, undefined values will be set to null before serialization.
// *
// * The ValueCheckingMode and PropertyConvertingMode determine whether an error will be thrown during
// * serialization or deserialization.
// */
// private _mapUndefinedToNull: boolean = false;
// /**
// * Determines whether a missing or undefined property value should be considered as null or not.
// *
// * If true, a missing JSON value will be added and set as null before deserialization.
// * For serialization, undefined values will be set to null before serialization.
// *
// * ValueCheckingMode and PropertyConvertingMode determine whether an error will be thrown during
// * serialization or deserialization.
// *
// * @see https://www.npmjs.com/package/json2typescript full documentation
// */
// get mapUndefinedToNull(): boolean {
// return this._mapUndefinedToNull;
// }
// /**
// * Determines whether a missing or undefined property value should be considered as null or not.
// *
// * If true, a missing JSON value will be added and set as null before deserialization.
// * For serialization, undefined values will be set to null before serialization.
// *
// * The ValueCheckingMode and PropertyConvertingMode determine whether an error will be thrown during
// * serialization or deserialization.
// *
// * @see https://www.npmjs.com/package/json2typescript full documentation
// */
// set mapUndefinedToNull(value: boolean) {
// this._mapUndefinedToNull = value;
// }
JsonConvert._converterCache = new Map();
JsonConvert._defaultSettings = new JsonConvertSettings();
JsonConvert._globalConverters = new Map();
//# sourceMappingURL=json-convert.js.map