UNPKG

@venly/venly-core-sdk

Version:

Javascrip/Typescript SDK for Venly's Web3 Services

1,066 lines 48.7 kB
"use strict"; 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