tserialize
Advanced tools
Comparing version 1.3.5 to 1.4.1
@@ -0,1 +1,6 @@ | ||
# 1.4.0 | ||
- Полный рефакторинг внутреннего хранилища данных, тесты проходит, но надо тестировать использование библиотеки в стороннем пакете | ||
- Использование reflect-metadata помечено как deprecated, в следующей версии будет выпилено | ||
- При наследовании дочерние классы не портят метаданные родительских классов | ||
# 1.3.5 | ||
@@ -2,0 +7,0 @@ - Исправлено неожиданное поведение при сериализации унаследованных моделей, когда пытались сериализоваться поля из |
@@ -5,3 +5,3 @@ // Generated by dts-bundle v0.7.2 | ||
* @description Хэлпер для сериализации классов, имеющих поля с навешанным декоратором JsonName. Сериализует только те | ||
* поля, у которых есть декоратор и задано начальное значение. | ||
* поля, у которых есть декоратор и есть значение. | ||
* @param model - экземпляр класса, который надо превратить в данные для отправки серверу по JSONRPC | ||
@@ -14,19 +14,68 @@ * @returns {{}} - обычный объект JS | ||
/** | ||
* Декоратор для сериализации-десериализации массивов экземпляров. | ||
* @param proto - конструктор класса, экземпляры которой лежат в массиве | ||
* @param {string} name - кастомное имя поля в сырых данных | ||
* @returns {(target: object, propertyKey: string) => void} - декоратор | ||
* @constructor | ||
*/ | ||
export function JsonArray(proto: any, name?: string): (target: object, propertyKey: string) => void; | ||
export function JsonMeta(): (target: object, propertyKey: string) => void; | ||
/** | ||
* Декоратор без аргументов для объявления структуры, чтобы мапить плоские данные в аггрегированные объекты | ||
* @returns {(target: object, propertyKey: string) => void} - декоратор | ||
* @constructor | ||
*/ | ||
export function JsonMeta(TargetClass?: any): (target: object, propertyKey: string) => void; | ||
/** | ||
* Декоратор для примитивного маппинга поля между экземпляром и сырыми данными | ||
* @param {string} name - кастомное имя поля, которое будет в сырых данных | ||
* @param {(value: T, instance: any) => any} serialize - функция-сериализатор, получает значение поля и экземпляр, вовзвращает значение. | ||
* Если значения нет - сериализатор не будет вызван и поле не попадет в результирующий объект. | ||
* Если сериализатор вернул null/undefined - значение так же не попадет в результирующий объект. | ||
* @param {(rawValue: any, rawData?: any) => T} deserialize - функция-десериализатор | ||
* @returns {(target: object, propertyKey: string) => void} - декоратор | ||
* @constructor | ||
*/ | ||
export function JsonName<T>(name?: string, serialize?: (value: T, instance: any) => any, deserialize?: (rawValue: any, rawData?: any) => T): (target: object, propertyKey: string) => void; | ||
/** | ||
* Декоратор для десериализации поля с сервера, но не на сервер | ||
* @param {string} name - кастомное имя поля, которое будет в сырых данных | ||
* @param {(rawValue: any, rawData?: any) => T} deserialize - функция-десериализатор | ||
* @returns {(target: object, propertyKey: string) => void} - декоратор | ||
* @constructor | ||
*/ | ||
export function JsonNameReadonly<T>(name?: string, deserialize?: (rawValue: any, rawData?: any) => T): (target: object, propertyKey: string) => void; | ||
export function JsonStruct(name?: string): (target: object, propertyKey: string) => void; | ||
/** | ||
* Декоратор для сериализаци-дерериализации аггрегированных моделей. | ||
* Для сериализации использует toServer метод экземпляра.Если его нет - просто serialize. | ||
* Для десериализации использует статический метод fromServer. Если его нет - просто deserialize. | ||
* @param TargetClass - конструктор аггрегированной модели | ||
* @param {string} rawName - кастомное имя поля в сырых данных | ||
* @returns {(target: object, propertyKey: string) => void} - декоратор | ||
* @constructor | ||
*/ | ||
export function JsonStruct(TargetClass?: any, rawName?: string): (target: object, propertyKey: string) => void; | ||
/** | ||
* Декоратор для маппинга, десериализация которого работает после всех остальных полей. Сиг | ||
* @param {string} name - кастомное имя поля, которое будет в сырых данных | ||
* @param {(value: T, instance: any) => any} serialize - функция-сериализатор, получает значение поля и экземпляр, вовзвращает значение. | ||
* Если значения нет - сериализатор не будет вызван и поле не попадет в результирующий объект. | ||
* Если сериализатор вернул null/undefined - значение так же не попадет в результирующий объект. | ||
* @param {(rawValue: any, rawData?: any) => T} deserialize - функция-десериализатор. | ||
* Работает когда все остальные поля объекта уже десериализованы | ||
* @returns {(target: object, propertyKey: string) => void} - декоратор | ||
* @constructor | ||
*/ | ||
export function JsonNameLate<T>(name?: string, serialize?: (value: T, instance: any) => any, deserialize?: (rawValue: any, rawData?: any) => T): (target: object, propertyKey: string) => void; | ||
/** | ||
* @description Хэлпер для разбора данных, пришедших по JSONRPC от сервера в нашу модель | ||
* @param data - данные от сервера | ||
* @param cls - класс, в экземпляр которого надо превратить данные | ||
* @returns {T} - экземпляр класса cls, заполненный данными | ||
* Хэлпер для десериализации сырых данных в экземпляр данного класса | ||
* @param data - сырые данные | ||
* @param {{new(...args: any[]): T}} cls - конструктор класса, в экземпляр которого надо превратить данные | ||
* @returns {T} - экземпляр | ||
*/ | ||
@@ -33,0 +82,0 @@ export function deserialize<T>(data: any, cls: { |
513
index.js
@@ -76,3 +76,3 @@ (function webpackUniversalModuleDefinition(root, factory) { | ||
/******/ // Load entry module and return exports | ||
/******/ return __webpack_require__(__webpack_require__.s = 12); | ||
/******/ return __webpack_require__(__webpack_require__.s = 16); | ||
/******/ }) | ||
@@ -87,7 +87,10 @@ /************************************************************************/ | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var store_1 = __webpack_require__(14); | ||
exports.MetaStore = store_1.MetaStore; | ||
var consts_1 = __webpack_require__(5); | ||
exports.JsonNameMetadataKey = consts_1.JsonNameMetadataKey; | ||
var root_store_1 = __webpack_require__(9); | ||
exports.RootMetaStore = root_store_1.RootMetaStore; | ||
var consts_1 = __webpack_require__(7); | ||
exports.ParentKey = consts_1.ParentKey; | ||
var class_meta_store_1 = __webpack_require__(4); | ||
exports.ClassMetaStore = class_meta_store_1.ClassMetaStore; | ||
var property_meta_builder_1 = __webpack_require__(8); | ||
exports.PropertyMetaBuilder = property_meta_builder_1.PropertyMetaBuilder; | ||
@@ -102,3 +105,3 @@ | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var deserialize_1 = __webpack_require__(11); | ||
var deserialize_1 = __webpack_require__(15); | ||
exports.deserialize = deserialize_1.deserialize; | ||
@@ -114,8 +117,17 @@ | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var utils_1 = __webpack_require__(0); | ||
var core_1 = __webpack_require__(0); | ||
/** | ||
* Декоратор для примитивного маппинга поля между экземпляром и сырыми данными | ||
* @param {string} name - кастомное имя поля, которое будет в сырых данных | ||
* @param {(value: T, instance: any) => any} serialize - функция-сериализатор, получает значение поля и экземпляр, вовзвращает значение. | ||
* Если значения нет - сериализатор не будет вызван и поле не попадет в результирующий объект. | ||
* Если сериализатор вернул null/undefined - значение так же не попадет в результирующий объект. | ||
* @param {(rawValue: any, rawData?: any) => T} deserialize - функция-десериализатор | ||
* @returns {(target: object, propertyKey: string) => void} - декоратор | ||
* @constructor | ||
*/ | ||
function JsonName(name, serialize, deserialize) { | ||
return function (target, propertyKey) { | ||
var metaStore = utils_1.MetaStore.getMetaStore(target); | ||
var rawKey = name ? name : propertyKey; | ||
metaStore.make(propertyKey, target).name(rawKey).serializator(serialize).deserializator(deserialize); | ||
var propertyMetadata = core_1.PropertyMetaBuilder.make(propertyKey, name).serializer(serialize).deserializer(deserialize).raw; | ||
core_1.RootMetaStore.setupPropertyMetadata(target, propertyMetadata); | ||
}; | ||
@@ -133,3 +145,3 @@ } | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var utils_1 = __webpack_require__(0); | ||
var core_1 = __webpack_require__(0); | ||
function serializeValue(metadata, value, instance) { | ||
@@ -151,3 +163,3 @@ if (!metadata) { | ||
var jsonName = metadata.rawKey; | ||
if (jsonName !== utils_1.ParentKey) { | ||
if (jsonName !== core_1.ParentKey) { | ||
result[jsonName] = serializedValue; | ||
@@ -162,3 +174,3 @@ } | ||
* @description Хэлпер для сериализации классов, имеющих поля с навешанным декоратором JsonName. Сериализует только те | ||
* поля, у которых есть декоратор и задано начальное значение. | ||
* поля, у которых есть декоратор и есть значение. | ||
* @param model - экземпляр класса, который надо превратить в данные для отправки серверу по JSONRPC | ||
@@ -169,11 +181,8 @@ * @returns {{}} - обычный объект JS | ||
var result = {}; | ||
var target = Object.getPrototypeOf(model); | ||
var metaStore = utils_1.MetaStore.getMetaStore(target); | ||
var modelKeys = metaStore.getPropertyKeys(); | ||
var targetClass = Object.getPrototypeOf(model); | ||
var metaStore = core_1.RootMetaStore.getClassMetaStore(targetClass); | ||
var modelKeys = metaStore.propertyKeys; | ||
for (var _i = 0, modelKeys_1 = modelKeys; _i < modelKeys_1.length; _i++) { | ||
var propertyKey = modelKeys_1[_i]; | ||
if (!metaStore.hasOwnProperty(target, propertyKey)) { | ||
continue; | ||
} | ||
var metadata = metaStore.getPropertyMeta(propertyKey); | ||
var metadata = metaStore.getMetadataByPropertyKey(propertyKey); | ||
var serializedValue = serializeValue(metadata, model[propertyKey], model); | ||
@@ -194,14 +203,64 @@ assignSerializedValueToResult(metadata, serializedValue, result); | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var utils_1 = __webpack_require__(0); | ||
var deserialize_1 = __webpack_require__(1); | ||
function JsonStruct(name) { | ||
return function (target, propertyKey) { | ||
var proto = Reflect.getMetadata('design:type', target, propertyKey); | ||
var metaStore = utils_1.MetaStore.getMetaStore(target); | ||
var rawKey = name ? name : propertyKey; | ||
var deserializer = proto.fromServer ? proto.fromServer : function (value) { return deserialize_1.deserialize(value, proto); }; | ||
metaStore.make(propertyKey, target).name(rawKey).deserializator(deserializer).struct(); | ||
var utils_1 = __webpack_require__(5); | ||
var ClassMetaStore = /** @class */ (function () { | ||
function ClassMetaStore() { | ||
/** | ||
* Хранилище метаданных для полей класса | ||
*/ | ||
this.propertiesMetaStore = {}; | ||
/** | ||
* @description Хранилище зависимостей "имя сырого поля" <-> "имя поля в объекте" | ||
*/ | ||
this.propertyKeyInversion = {}; | ||
} | ||
ClassMetaStore.prototype.addPropertyMetadata = function (propertyMetadata) { | ||
this.propertiesMetaStore[propertyMetadata.propertyKey] = propertyMetadata; | ||
this.propertyKeyInversion[propertyMetadata.rawKey] = propertyMetadata.propertyKey; | ||
}; | ||
} | ||
exports.JsonStruct = JsonStruct; | ||
Object.defineProperty(ClassMetaStore.prototype, "propertyKeys", { | ||
get: function () { | ||
return Object.keys(this.propertiesMetaStore); | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
/** | ||
* Получить метаданные поля по ключу нативного экземпляра. Нужно для сериализации | ||
*/ | ||
ClassMetaStore.prototype.getMetadataByPropertyKey = function (propertyKey) { | ||
return this.propertiesMetaStore[propertyKey]; | ||
}; | ||
/** | ||
* Получить метаданные поля по ключу сырых данных. Нужно для десериализации | ||
*/ | ||
ClassMetaStore.prototype.getMetadataByRawKey = function (rawKey) { | ||
return this.propertiesMetaStore[this.propertyKeyInversion[rawKey]]; | ||
}; | ||
ClassMetaStore.prototype.updateWithParentStore = function (parentStore) { | ||
var newPropertiesMetaStore = utils_1.clone(parentStore.propertiesMetaStore); | ||
var newPropertyKeyInversion = utils_1.clone(parentStore.propertyKeyInversion); | ||
var ownPropertiesKeys = Object.keys(this.propertiesMetaStore); | ||
for (var _i = 0, ownPropertiesKeys_1 = ownPropertiesKeys; _i < ownPropertiesKeys_1.length; _i++) { | ||
var ownPropertyKey = ownPropertiesKeys_1[_i]; | ||
var ownPropertyMetadata = this.getMetadataByPropertyKey(ownPropertyKey); | ||
// Если поле не унаследовано - просто закинем в хранилище и добавим инверсию | ||
if (!newPropertiesMetaStore[ownPropertyKey]) { | ||
newPropertiesMetaStore[ownPropertyKey] = this.propertiesMetaStore[ownPropertyKey]; | ||
newPropertyKeyInversion[ownPropertyMetadata.rawKey] = ownPropertyMetadata.propertyKey; | ||
continue; | ||
} | ||
var overridePropertyMetadata = newPropertiesMetaStore[ownPropertyKey]; | ||
delete newPropertyKeyInversion[overridePropertyMetadata.rawKey]; | ||
// В общем, все кроме propertyKey и rawKey по умолчанию отсутствуют, и Object.assign нормально их накинет. | ||
// Соответственно если поле в родителе было late или struct, а у потомка будет просто JsonName - сменятся имена, | ||
// если навешаны серилизаторы-десериализаторы - они тоже. | ||
Object.assign(overridePropertyMetadata, ownPropertyMetadata); | ||
newPropertyKeyInversion[overridePropertyMetadata.rawKey] = overridePropertyMetadata.propertyKey; | ||
} | ||
this.propertiesMetaStore = newPropertiesMetaStore; | ||
this.propertyKeyInversion = newPropertyKeyInversion; | ||
}; | ||
return ClassMetaStore; | ||
}()); | ||
exports.ClassMetaStore = ClassMetaStore; | ||
@@ -216,4 +275,26 @@ | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.JsonNameMetadataKey = 'JsonName'; | ||
exports.ParentKey = '@JsonNameParentKey'; | ||
function getNameOfClass(target) { | ||
return target.constructor.name; | ||
} | ||
exports.getNameOfClass = getNameOfClass; | ||
function getParentClass(target) { | ||
return Object.getPrototypeOf(target); | ||
} | ||
exports.getParentClass = getParentClass; | ||
function clone(from) { | ||
if (from === null || typeof from !== 'object') | ||
return from; | ||
if (from.constructor !== Object && from.constructor !== Array) | ||
return from; | ||
if (from.constructor === Date || from.constructor === RegExp || from.constructor === Function || | ||
from.constructor === String || from.constructor === Number || from.constructor === Boolean) { | ||
return new from.constructor(from); | ||
} | ||
var to = new from.constructor(); | ||
for (var name_1 in from) { | ||
to[name_1] = typeof to[name_1] === 'undefined' ? clone(from[name_1]) : to[name_1]; | ||
} | ||
return to; | ||
} | ||
exports.clone = clone; | ||
@@ -228,13 +309,13 @@ | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var JsonArray_1 = __webpack_require__(7); | ||
var JsonArray_1 = __webpack_require__(10); | ||
exports.JsonArray = JsonArray_1.JsonArray; | ||
var JsonMeta_1 = __webpack_require__(8); | ||
var JsonMeta_1 = __webpack_require__(11); | ||
exports.JsonMeta = JsonMeta_1.JsonMeta; | ||
var JsonName_1 = __webpack_require__(2); | ||
exports.JsonName = JsonName_1.JsonName; | ||
var JsonNameReadonly_1 = __webpack_require__(10); | ||
var JsonNameReadonly_1 = __webpack_require__(13); | ||
exports.JsonNameReadonly = JsonNameReadonly_1.JsonNameReadonly; | ||
var JsonStruct_1 = __webpack_require__(4); | ||
var JsonStruct_1 = __webpack_require__(14); | ||
exports.JsonStruct = JsonStruct_1.JsonStruct; | ||
var JsonNameLate_1 = __webpack_require__(9); | ||
var JsonNameLate_1 = __webpack_require__(12); | ||
exports.JsonNameLate = JsonNameLate_1.JsonNameLate; | ||
@@ -250,5 +331,114 @@ | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ParentKey = '@JsonNameParentKey'; | ||
/***/ }), | ||
/* 8 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var PropertyMetaBuilder = /** @class */ (function () { | ||
function PropertyMetaBuilder() { | ||
this.data = { | ||
propertyKey: null, | ||
rawKey: null | ||
}; | ||
} | ||
PropertyMetaBuilder.make = function (propertyKey, name) { | ||
var retVal = new PropertyMetaBuilder(); | ||
retVal.data.propertyKey = propertyKey; | ||
retVal.data.rawKey = name || propertyKey; | ||
return retVal; | ||
}; | ||
PropertyMetaBuilder.prototype.struct = function () { | ||
this.data.isStruct = true; | ||
return this; | ||
}; | ||
PropertyMetaBuilder.prototype.late = function () { | ||
this.data.isLate = true; | ||
return this; | ||
}; | ||
PropertyMetaBuilder.prototype.serializer = function (serializeFunc) { | ||
if (!serializeFunc) { | ||
return this; | ||
} | ||
this.data.serialize = serializeFunc; | ||
return this; | ||
}; | ||
PropertyMetaBuilder.prototype.deserializer = function (deserializeFunc) { | ||
if (!deserializeFunc) { | ||
return this; | ||
} | ||
this.data.deserialize = deserializeFunc; | ||
return this; | ||
}; | ||
Object.defineProperty(PropertyMetaBuilder.prototype, "raw", { | ||
get: function () { | ||
return this.data; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
return PropertyMetaBuilder; | ||
}()); | ||
exports.PropertyMetaBuilder = PropertyMetaBuilder; | ||
/***/ }), | ||
/* 9 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var class_meta_store_1 = __webpack_require__(4); | ||
var utils_1 = __webpack_require__(5); | ||
var RootMetaStore = /** @class */ (function () { | ||
function RootMetaStore() { | ||
} | ||
RootMetaStore.setupPropertyMetadata = function (targetClass, propertyMetadata) { | ||
if (!this.store.has(targetClass)) { | ||
this.store.set(targetClass, new class_meta_store_1.ClassMetaStore()); | ||
} | ||
var classFieldsMetaStore = this.store.get(targetClass); | ||
classFieldsMetaStore.addPropertyMetadata(propertyMetadata); | ||
this.updateClassMetaByParent(targetClass); | ||
}; | ||
RootMetaStore.updateClassMetaByParent = function (targetClass) { | ||
var parentClass = utils_1.getParentClass(targetClass); | ||
if (utils_1.getNameOfClass(parentClass) === 'Object') { | ||
return; | ||
} | ||
var parentStore = this.store.get(utils_1.getParentClass(targetClass)); | ||
var targetStore = this.store.get(targetClass); | ||
targetStore.updateWithParentStore(parentStore); | ||
}; | ||
RootMetaStore.getClassMetaStore = function (targetClass) { | ||
return this.store.get(targetClass); | ||
}; | ||
RootMetaStore.store = new Map(); | ||
return RootMetaStore; | ||
}()); | ||
exports.RootMetaStore = RootMetaStore; | ||
/***/ }), | ||
/* 10 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var JsonName_1 = __webpack_require__(2); | ||
var serialize_1 = __webpack_require__(13); | ||
var serialize_1 = __webpack_require__(17); | ||
var deserialize_1 = __webpack_require__(1); | ||
/** | ||
* Декоратор для сериализации-десериализации массивов экземпляров. | ||
* @param proto - конструктор класса, экземпляры которой лежат в массиве | ||
* @param {string} name - кастомное имя поля в сырых данных | ||
* @returns {(target: object, propertyKey: string) => void} - декоратор | ||
* @constructor | ||
*/ | ||
function JsonArray(proto, name) { | ||
@@ -277,3 +467,3 @@ var serializer = function (value) { | ||
/***/ }), | ||
/* 8 */ | ||
/* 11 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
@@ -284,6 +474,21 @@ | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var utils_1 = __webpack_require__(0); | ||
var JsonStruct_1 = __webpack_require__(4); | ||
function JsonMeta() { | ||
return JsonStruct_1.JsonStruct.call(null, utils_1.ParentKey); | ||
var core_1 = __webpack_require__(0); | ||
var deserialize_1 = __webpack_require__(1); | ||
/** | ||
* Декоратор без аргументов для объявления структуры, чтобы мапить плоские данные в аггрегированные объекты | ||
* @returns {(target: object, propertyKey: string) => void} - декоратор | ||
* @constructor | ||
*/ | ||
function JsonMeta(TargetClass) { | ||
return function (target, propertyKey) { | ||
var isDeprecatedUsage = !TargetClass || typeof TargetClass === 'string'; | ||
if (isDeprecatedUsage) { | ||
var targetClassName = Reflect.getMetadata('design:type', target, propertyKey).name; | ||
console.error("JsonMeta signature has changed, use(copy it) \"JsonMeta(" + targetClassName + ")\""); | ||
} | ||
var proto = isDeprecatedUsage ? Reflect.getMetadata('design:type', target, propertyKey) : TargetClass; | ||
var deserializeFunc = proto.fromServer ? proto.fromServer : function (value) { return deserialize_1.deserialize(value, proto); }; | ||
var propertyMetadata = core_1.PropertyMetaBuilder.make(propertyKey, core_1.ParentKey).deserializer(deserializeFunc).struct().raw; | ||
core_1.RootMetaStore.setupPropertyMetadata(target, propertyMetadata); | ||
}; | ||
} | ||
@@ -294,3 +499,3 @@ exports.JsonMeta = JsonMeta; | ||
/***/ }), | ||
/* 9 */ | ||
/* 12 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
@@ -301,8 +506,18 @@ | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var utils_1 = __webpack_require__(0); | ||
var core_1 = __webpack_require__(0); | ||
/** | ||
* Декоратор для маппинга, десериализация которого работает после всех остальных полей. Сиг | ||
* @param {string} name - кастомное имя поля, которое будет в сырых данных | ||
* @param {(value: T, instance: any) => any} serialize - функция-сериализатор, получает значение поля и экземпляр, вовзвращает значение. | ||
* Если значения нет - сериализатор не будет вызван и поле не попадет в результирующий объект. | ||
* Если сериализатор вернул null/undefined - значение так же не попадет в результирующий объект. | ||
* @param {(rawValue: any, rawData?: any) => T} deserialize - функция-десериализатор. | ||
* Работает когда все остальные поля объекта уже десериализованы | ||
* @returns {(target: object, propertyKey: string) => void} - декоратор | ||
* @constructor | ||
*/ | ||
function JsonNameLate(name, serialize, deserialize) { | ||
return function (target, propertyKey) { | ||
var metaStore = utils_1.MetaStore.getMetaStore(target); | ||
var rawKey = name ? name : propertyKey; | ||
metaStore.make(propertyKey, target).name(rawKey).serializator(serialize).deserializator(deserialize).late(); | ||
var propertyMetadata = core_1.PropertyMetaBuilder.make(propertyKey, name).serializer(serialize).deserializer(deserialize).late().raw; | ||
core_1.RootMetaStore.setupPropertyMetadata(target, propertyMetadata); | ||
}; | ||
@@ -314,3 +529,3 @@ } | ||
/***/ }), | ||
/* 10 */ | ||
/* 13 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
@@ -322,2 +537,9 @@ | ||
var JsonName_1 = __webpack_require__(2); | ||
/** | ||
* Декоратор для десериализации поля с сервера, но не на сервер | ||
* @param {string} name - кастомное имя поля, которое будет в сырых данных | ||
* @param {(rawValue: any, rawData?: any) => T} deserialize - функция-десериализатор | ||
* @returns {(target: object, propertyKey: string) => void} - декоратор | ||
* @constructor | ||
*/ | ||
function JsonNameReadonly(name, deserialize) { | ||
@@ -330,3 +552,3 @@ return JsonName_1.JsonName.call(null, name, function () { return null; }, deserialize); | ||
/***/ }), | ||
/* 11 */ | ||
/* 14 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
@@ -337,17 +559,53 @@ | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var utils_1 = __webpack_require__(0); | ||
var core_1 = __webpack_require__(0); | ||
var deserialize_1 = __webpack_require__(1); | ||
/** | ||
* @description Хэлпер для разбора данных, пришедших по JSONRPC от сервера в нашу модель | ||
* @param data - данные от сервера | ||
* @param cls - класс, в экземпляр которого надо превратить данные | ||
* @returns {T} - экземпляр класса cls, заполненный данными | ||
* Декоратор для сериализаци-дерериализации аггрегированных моделей. | ||
* Для сериализации использует toServer метод экземпляра.Если его нет - просто serialize. | ||
* Для десериализации использует статический метод fromServer. Если его нет - просто deserialize. | ||
* @param TargetClass - конструктор аггрегированной модели | ||
* @param {string} rawName - кастомное имя поля в сырых данных | ||
* @returns {(target: object, propertyKey: string) => void} - декоратор | ||
* @constructor | ||
*/ | ||
function JsonStruct(TargetClass, rawName) { | ||
return function (target, propertyKey) { | ||
var isDeprecatedUsage = !TargetClass || typeof TargetClass === 'string'; | ||
if (isDeprecatedUsage) { | ||
var targetClassName = Reflect.getMetadata('design:type', target, propertyKey).name; | ||
console.error("JsonStruct signature has changed, use(copy it) \"JsonStruct(" + targetClassName + (TargetClass ? ", '" + TargetClass + "'" : '') + ")\""); | ||
} | ||
var proto = isDeprecatedUsage ? Reflect.getMetadata('design:type', target, propertyKey) : TargetClass; | ||
var name = isDeprecatedUsage ? TargetClass : rawName; | ||
var deserializeFunc = proto.fromServer ? proto.fromServer : function (value) { return deserialize_1.deserialize(value, proto); }; | ||
var propertyMetadata = core_1.PropertyMetaBuilder.make(propertyKey, name).deserializer(deserializeFunc).struct().raw; | ||
core_1.RootMetaStore.setupPropertyMetadata(target, propertyMetadata); | ||
}; | ||
} | ||
exports.JsonStruct = JsonStruct; | ||
/***/ }), | ||
/* 15 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var core_1 = __webpack_require__(0); | ||
/** | ||
* Хэлпер для десериализации сырых данных в экземпляр данного класса | ||
* @param data - сырые данные | ||
* @param {{new(...args: any[]): T}} cls - конструктор класса, в экземпляр которого надо превратить данные | ||
* @returns {T} - экземпляр | ||
*/ | ||
function deserialize(data, cls) { | ||
var retVal = new cls(); | ||
var target = Object.getPrototypeOf(retVal); | ||
var metaStore = Reflect.getMetadata(utils_1.JsonNameMetadataKey, target); | ||
var targetClass = Object.getPrototypeOf(retVal); | ||
var metaStore = core_1.RootMetaStore.getClassMetaStore(targetClass); | ||
var lateFields = []; | ||
for (var _i = 0, _a = metaStore.getPropertyKeys(); _i < _a.length; _i++) { | ||
var propertyKey = _a[_i]; | ||
var serializeProps = metaStore.getPropertyMeta(propertyKey); | ||
var modelKeys = metaStore.propertyKeys; | ||
for (var _i = 0, modelKeys_1 = modelKeys; _i < modelKeys_1.length; _i++) { | ||
var propertyKey = modelKeys_1[_i]; | ||
var serializeProps = metaStore.getMetadataByPropertyKey(propertyKey); | ||
if (serializeProps.isLate) { | ||
@@ -360,3 +618,3 @@ lateFields.push(propertyKey); | ||
var jsonName = serializeProps.rawKey; | ||
var jsonValue = jsonName !== utils_1.ParentKey ? data[jsonName] : data; | ||
var jsonValue = jsonName !== core_1.ParentKey ? data[jsonName] : data; | ||
if (typeof jsonValue !== 'undefined') { | ||
@@ -368,9 +626,9 @@ retVal[serializeProps.propertyKey] = deserialize_1 ? deserialize_1(jsonValue, data) : jsonValue; | ||
// TODO remove duplicate | ||
for (var _b = 0, lateFields_1 = lateFields; _b < lateFields_1.length; _b++) { | ||
var propertyKey = lateFields_1[_b]; | ||
var serializeProps = metaStore.getPropertyMeta(propertyKey); | ||
for (var _a = 0, lateFields_1 = lateFields; _a < lateFields_1.length; _a++) { | ||
var propertyKey = lateFields_1[_a]; | ||
var serializeProps = metaStore.getMetadataByPropertyKey(propertyKey); | ||
if (serializeProps) { | ||
var deserialize_2 = serializeProps.deserialize; | ||
var jsonName = serializeProps.rawKey; | ||
var jsonValue = jsonName !== utils_1.ParentKey ? data[jsonName] : data; | ||
var jsonValue = jsonName !== core_1.ParentKey ? data[jsonName] : data; | ||
if (typeof jsonValue !== 'undefined') { | ||
@@ -387,3 +645,3 @@ retVal[serializeProps.propertyKey] = deserialize_2 ? deserialize_2(jsonValue, retVal) : jsonValue; | ||
/***/ }), | ||
/* 12 */ | ||
/* 16 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
@@ -408,3 +666,3 @@ | ||
/***/ }), | ||
/* 13 */ | ||
/* 17 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
@@ -419,123 +677,4 @@ | ||
/***/ }), | ||
/* 14 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var consts_1 = __webpack_require__(5); | ||
var MetaStore = /** @class */ (function () { | ||
function MetaStore() { | ||
/** | ||
* @description Для имени поля в классе хранит его мета-информацию | ||
*/ | ||
this.propertiesMetaStore = {}; | ||
/** | ||
* @description Хранит зависимость "сырое поле" <-> "поле в объекте" | ||
*/ | ||
this.keyPropertyInversion = {}; | ||
/** | ||
* @description Простое хранилище всех декорированных полей, нужно для восстановления объекта | ||
*/ | ||
this.propertyKeys = []; | ||
/** | ||
* @description Поле для хранения промежуточного значения ключа, с которым работает builder | ||
*/ | ||
this.currentPropertyKey = null; | ||
this.significantFieldsForTarget = {}; | ||
} | ||
Object.defineProperty(MetaStore.prototype, "currentMetadata", { | ||
get: function () { | ||
return this.propertiesMetaStore[this.currentPropertyKey]; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
MetaStore.getMetaStore = function (target) { | ||
if (!Reflect.hasMetadata(consts_1.JsonNameMetadataKey, target)) { | ||
Reflect.defineMetadata(consts_1.JsonNameMetadataKey, new MetaStore(), target); | ||
} | ||
return Reflect.getMetadata(consts_1.JsonNameMetadataKey, target); | ||
}; | ||
MetaStore.prototype.make = function (propertyKey, target) { | ||
this.currentPropertyKey = propertyKey; | ||
if (this.currentMetadata) { | ||
console.warn("Property \"" + propertyKey + "\" already have metadata for serialization"); | ||
} | ||
var targetConstructorName = target.constructor.name; | ||
if (!this.significantFieldsForTarget[targetConstructorName]) { | ||
this.significantFieldsForTarget[targetConstructorName] = []; | ||
} | ||
this.significantFieldsForTarget[targetConstructorName].push(propertyKey); | ||
this.propertiesMetaStore[propertyKey] = this.currentMetadata || { | ||
propertyKey: propertyKey, | ||
rawKey: propertyKey, | ||
isStruct: false, | ||
isLate: false | ||
}; | ||
this.propertyKeys.push(propertyKey); | ||
this.keyPropertyInversion[propertyKey] = propertyKey; | ||
return this; | ||
}; | ||
MetaStore.prototype.name = function (rawKey) { | ||
if (!rawKey) { | ||
return this; | ||
} | ||
this.currentMetadata.rawKey = rawKey; | ||
delete this.keyPropertyInversion[this.currentPropertyKey]; | ||
this.keyPropertyInversion[rawKey] = this.currentPropertyKey; | ||
return this; | ||
}; | ||
MetaStore.prototype.struct = function () { | ||
this.currentMetadata.isStruct = true; | ||
return this; | ||
}; | ||
MetaStore.prototype.late = function () { | ||
this.currentMetadata.isLate = true; | ||
return this; | ||
}; | ||
MetaStore.prototype.serializator = function (serializator) { | ||
if (!serializator) { | ||
return this; | ||
} | ||
this.currentMetadata.serialize = serializator; | ||
return this; | ||
}; | ||
MetaStore.prototype.deserializator = function (deserializator) { | ||
if (!deserializator) { | ||
return this; | ||
} | ||
this.currentMetadata.deserialize = deserializator; | ||
return this; | ||
}; | ||
MetaStore.prototype.addStructProperty = function (propertyName, target) { | ||
console.log('add struct property', propertyName, target, target.fromServer); | ||
}; | ||
MetaStore.prototype.getPropertyMeta = function (propertyKey) { | ||
return this.propertiesMetaStore[propertyKey]; | ||
}; | ||
MetaStore.prototype.getPropertyKeys = function () { | ||
return this.propertyKeys; | ||
}; | ||
MetaStore.prototype.getTargetKeyMeta = function (targetKey) { | ||
var propertyKey = this.keyPropertyInversion[targetKey]; | ||
return propertyKey ? this.propertiesMetaStore[propertyKey] : null; | ||
}; | ||
MetaStore.prototype.hasOwnProperty = function (target, propertyKey) { | ||
if ((this.significantFieldsForTarget[target.constructor.name] || []).includes(propertyKey)) { | ||
return true; | ||
} | ||
while (target.__proto__) { | ||
return this.hasOwnProperty(target.__proto__, propertyKey); | ||
} | ||
return false; | ||
}; | ||
return MetaStore; | ||
}()); | ||
exports.MetaStore = MetaStore; | ||
/***/ }) | ||
/******/ ]); | ||
}); |
{ | ||
"name": "tserialize", | ||
"version": "1.3.5", | ||
"version": "1.4.1", | ||
"description": "TypeScript serialize utils", | ||
@@ -13,3 +13,3 @@ "types": "index.d.ts", | ||
"scripts": { | ||
"test": "node_modules/.bin/mocha -r ts-node/register test/**/*.ts", | ||
"test": "jest", | ||
"lint-code": "node_modules/.bin/tslint -c ./tslint.json -p ./tsconfig.json --type-check", | ||
@@ -24,2 +24,3 @@ "build": "webpack" | ||
"serialize", | ||
"mapper", | ||
"decorators", | ||
@@ -36,7 +37,4 @@ "deserialize", | ||
"devDependencies": { | ||
"@types/chai": "^4.0.3", | ||
"@types/mocha": "^2.2.41", | ||
"chai": "4.1.1", | ||
"dts-bundle": "0.7.2", | ||
"mocha": "3.5.0", | ||
"jest": "22.4.3", | ||
"nyc": "11.2.1", | ||
@@ -51,3 +49,14 @@ "ts-loader": "2.3.2", | ||
"reflect-metadata": "0.1.10" | ||
}, | ||
"jest": { | ||
"verbose": true, | ||
"transform": { | ||
"^.+\\.ts$": "./test-preprocessor.js" | ||
}, | ||
"moduleFileExtensions": [ | ||
"js", | ||
"ts" | ||
], | ||
"testRegex": "test/.+/.+\\.ts" | ||
} | ||
} |
# Утилиты сериализации/десериализации для TypeScript и ES6 | ||
[![Build Status](https://travis-ci.org/SoEasy/tserialize.svg?branch=master)](https://travis-ci.org/SoEasy/tserialize) | ||
<img src="img/logo.svg" width="300" align="center"> | ||
<br/> | ||
@@ -11,4 +13,6 @@ ## Установка | ||
### Change overview | ||
Версия поднялась до 1.2.2 | ||
- Добавлен валидатор JsonArray | ||
Версия поднялась до 1.4.0 | ||
- Переписано внутреннее хранилище метаданных | ||
- Bсправлены баги при наследовании моделей | ||
- Начался процесс отказа от reflect-metadata | ||
@@ -49,3 +53,3 @@ ## Основная информация | ||
- Передать их аргументами в конструктор | ||
- Создать static-метод, который будет принимать данные и создавать из них экземпляр | ||
- Создать фабричный метод, который будет принимать данные и создавать из них экземпляр | ||
- Создать метод, который применяет к экземпляру переданные данные | ||
@@ -238,5 +242,7 @@ | ||
function JsonStruct( | ||
proto: any | ||
name?: string | ||
) | ||
``` | ||
- proto - конструктор класса вложенной структуры | ||
- name - название ключа для данных | ||
@@ -255,3 +261,3 @@ | ||
class Computer { | ||
@JsonStruct('sys_info') | ||
@JsonStruct(SysInfo, 'sys_info') | ||
os: SysInfo; | ||
@@ -274,8 +280,10 @@ | ||
Подобен JsonStruct, но данные берет не из ключа, а из исходного объекта. Нужен для преобразования плоских-композитных моделей. | ||
Например, объект чистых данных содержит овер9000 ключей, которые по логике относятся к разным сущностям. И вы, как хороший разработчик, хотите осуществить декомпозицию на мелкие самостоятельные сущности. | ||
Например, объект чистых данных содержит овер9000 ключей, которые по логике относятся к разным сущностям. | ||
И вы, как хороший разработчик, хотите осуществить декомпозицию на мелкие самостоятельные сущности. | ||
##### Сигнатура | ||
``` | ||
function JsonMeta() | ||
function JsonMeta(proto: any) | ||
``` | ||
- proto - конструктор класса, в который будет выделяться плоская структура | ||
@@ -293,3 +301,3 @@ ##### Пример | ||
class Computer { | ||
@JsonMeta() | ||
@JsonMeta(SysInfo) | ||
os: SysInfo; | ||
@@ -316,5 +324,5 @@ | ||
``` | ||
function JsonArray(Prototype, name) | ||
function JsonArray(proto, name) | ||
``` | ||
Prototype - класс, экземпляры которого будут храниться в массиве | ||
proto - класс, экземпляры которого будут храниться в массиве | ||
@@ -321,0 +329,0 @@ ##### Пример |
@@ -5,2 +5,9 @@ import { JsonName } from './JsonName'; | ||
/** | ||
* Декоратор для сериализации-десериализации массивов экземпляров. | ||
* @param proto - конструктор класса, экземпляры которой лежат в массиве | ||
* @param {string} name - кастомное имя поля в сырых данных | ||
* @returns {(target: object, propertyKey: string) => void} - декоратор | ||
* @constructor | ||
*/ | ||
export function JsonArray(proto: any, name?: string): (target: object, propertyKey: string) => void { | ||
@@ -7,0 +14,0 @@ const serializer = (value): any => { |
@@ -1,6 +0,27 @@ | ||
import { ParentKey } from './../utils'; | ||
import { JsonStruct } from './JsonStruct'; | ||
import {ParentKey, PropertyMetaBuilder, RootMetaStore} from '../core'; | ||
import { deserialize } from '../deserialize'; | ||
export function JsonMeta(): (target: object, propertyKey: string) => void { | ||
return JsonStruct.call(null, ParentKey); | ||
/** | ||
* Декоратор без аргументов для объявления структуры, чтобы мапить плоские данные в аггрегированные объекты | ||
* @returns {(target: object, propertyKey: string) => void} - декоратор | ||
* @constructor | ||
*/ | ||
export function JsonMeta(TargetClass?: any): (target: object, propertyKey: string) => void { | ||
return (target: object, propertyKey: string): void => { | ||
const isDeprecatedUsage = !TargetClass || typeof TargetClass === 'string'; | ||
if (isDeprecatedUsage) { | ||
const targetClassName = (Reflect as any).getMetadata('design:type', target, propertyKey).name; | ||
console.error( | ||
`JsonMeta signature has changed, use(copy it) "JsonMeta(${targetClassName})"` | ||
); | ||
} | ||
const proto = isDeprecatedUsage ? (Reflect as any).getMetadata('design:type', target, propertyKey) : TargetClass; | ||
const deserializeFunc = proto.fromServer ? proto.fromServer : (value): any => deserialize(value, proto); | ||
const propertyMetadata = PropertyMetaBuilder.make(propertyKey, ParentKey).deserializer(deserializeFunc).struct().raw; | ||
RootMetaStore.setupPropertyMetadata(target, propertyMetadata); | ||
}; | ||
} |
@@ -1,3 +0,13 @@ | ||
import { MetaStore } from './../utils'; | ||
import { PropertyMetaBuilder, RootMetaStore } from '../core'; | ||
/** | ||
* Декоратор для примитивного маппинга поля между экземпляром и сырыми данными | ||
* @param {string} name - кастомное имя поля, которое будет в сырых данных | ||
* @param {(value: T, instance: any) => any} serialize - функция-сериализатор, получает значение поля и экземпляр, вовзвращает значение. | ||
* Если значения нет - сериализатор не будет вызван и поле не попадет в результирующий объект. | ||
* Если сериализатор вернул null/undefined - значение так же не попадет в результирующий объект. | ||
* @param {(rawValue: any, rawData?: any) => T} deserialize - функция-десериализатор | ||
* @returns {(target: object, propertyKey: string) => void} - декоратор | ||
* @constructor | ||
*/ | ||
export function JsonName<T>( | ||
@@ -9,6 +19,5 @@ name?: string, | ||
return (target: object, propertyKey: string): void => { | ||
const metaStore: MetaStore = MetaStore.getMetaStore(target); | ||
const rawKey = name ? name : propertyKey; | ||
metaStore.make(propertyKey, target).name(rawKey).serializator(serialize).deserializator(deserialize); | ||
const propertyMetadata = PropertyMetaBuilder.make(propertyKey, name).serializer(serialize).deserializer(deserialize).raw; | ||
RootMetaStore.setupPropertyMetadata(target, propertyMetadata); | ||
}; | ||
} |
@@ -1,3 +0,14 @@ | ||
import { MetaStore } from './../utils'; | ||
import { PropertyMetaBuilder, RootMetaStore } from '../core'; | ||
/** | ||
* Декоратор для маппинга, десериализация которого работает после всех остальных полей. Сиг | ||
* @param {string} name - кастомное имя поля, которое будет в сырых данных | ||
* @param {(value: T, instance: any) => any} serialize - функция-сериализатор, получает значение поля и экземпляр, вовзвращает значение. | ||
* Если значения нет - сериализатор не будет вызван и поле не попадет в результирующий объект. | ||
* Если сериализатор вернул null/undefined - значение так же не попадет в результирующий объект. | ||
* @param {(rawValue: any, rawData?: any) => T} deserialize - функция-десериализатор. | ||
* Работает когда все остальные поля объекта уже десериализованы | ||
* @returns {(target: object, propertyKey: string) => void} - декоратор | ||
* @constructor | ||
*/ | ||
export function JsonNameLate<T>( | ||
@@ -9,6 +20,5 @@ name?: string, | ||
return (target: object, propertyKey: string): void => { | ||
const metaStore: MetaStore = MetaStore.getMetaStore(target); | ||
const rawKey = name ? name : propertyKey; | ||
metaStore.make(propertyKey, target).name(rawKey).serializator(serialize).deserializator(deserialize).late(); | ||
const propertyMetadata = PropertyMetaBuilder.make(propertyKey, name).serializer(serialize).deserializer(deserialize).late().raw; | ||
RootMetaStore.setupPropertyMetadata(target, propertyMetadata); | ||
}; | ||
} |
import { JsonName } from './JsonName'; | ||
/** | ||
* Декоратор для десериализации поля с сервера, но не на сервер | ||
* @param {string} name - кастомное имя поля, которое будет в сырых данных | ||
* @param {(rawValue: any, rawData?: any) => T} deserialize - функция-десериализатор | ||
* @returns {(target: object, propertyKey: string) => void} - декоратор | ||
* @constructor | ||
*/ | ||
export function JsonNameReadonly<T>( | ||
@@ -4,0 +11,0 @@ name?: string, |
@@ -1,14 +0,32 @@ | ||
import { MetaStore } from './../utils'; | ||
import { PropertyMetaBuilder, RootMetaStore } from './../core'; | ||
import { deserialize } from './../deserialize'; | ||
export function JsonStruct(name?: string): (target: object, propertyKey: string) => void { | ||
/** | ||
* Декоратор для сериализаци-дерериализации аггрегированных моделей. | ||
* Для сериализации использует toServer метод экземпляра.Если его нет - просто serialize. | ||
* Для десериализации использует статический метод fromServer. Если его нет - просто deserialize. | ||
* @param TargetClass - конструктор аггрегированной модели | ||
* @param {string} rawName - кастомное имя поля в сырых данных | ||
* @returns {(target: object, propertyKey: string) => void} - декоратор | ||
* @constructor | ||
*/ | ||
export function JsonStruct(TargetClass?: any, rawName?: string): (target: object, propertyKey: string) => void { | ||
return (target: object, propertyKey: string): void => { | ||
const proto = (Reflect as any).getMetadata('design:type', target, propertyKey); | ||
const metaStore: MetaStore = MetaStore.getMetaStore(target); | ||
const isDeprecatedUsage = !TargetClass || typeof TargetClass === 'string'; | ||
const rawKey = name ? name : propertyKey; | ||
const deserializer = proto.fromServer ? proto.fromServer : (value): any => deserialize(value, proto); | ||
if (isDeprecatedUsage) { | ||
const targetClassName = (Reflect as any).getMetadata('design:type', target, propertyKey).name; | ||
console.error( | ||
`JsonStruct signature has changed, use(copy it) "JsonStruct(${targetClassName}${TargetClass ? `, '${TargetClass}'` : ''})"` | ||
); | ||
} | ||
metaStore.make(propertyKey, target).name(rawKey).deserializator(deserializer).struct(); | ||
const proto = isDeprecatedUsage ? (Reflect as any).getMetadata('design:type', target, propertyKey) : TargetClass; | ||
const name = isDeprecatedUsage ? TargetClass : rawName; | ||
const deserializeFunc = proto.fromServer ? proto.fromServer : (value): any => deserialize(value, proto); | ||
const propertyMetadata = PropertyMetaBuilder.make(propertyKey, name).deserializer(deserializeFunc).struct().raw; | ||
RootMetaStore.setupPropertyMetadata(target, propertyMetadata); | ||
}; | ||
} |
@@ -1,17 +0,18 @@ | ||
import { JsonNameMetadataKey, ParentKey, MetaStore } from './../utils'; | ||
import { ClassMetaStore, ParentKey, RootMetaStore } from './../core'; | ||
/** | ||
* @description Хэлпер для разбора данных, пришедших по JSONRPC от сервера в нашу модель | ||
* @param data - данные от сервера | ||
* @param cls - класс, в экземпляр которого надо превратить данные | ||
* @returns {T} - экземпляр класса cls, заполненный данными | ||
* Хэлпер для десериализации сырых данных в экземпляр данного класса | ||
* @param data - сырые данные | ||
* @param {{new(...args: any[]): T}} cls - конструктор класса, в экземпляр которого надо превратить данные | ||
* @returns {T} - экземпляр | ||
*/ | ||
export function deserialize<T>(data: any, cls: { new (...args: Array<any>): T }): T { | ||
const retVal = new cls(); | ||
const target = Object.getPrototypeOf(retVal); | ||
const metaStore: MetaStore = (Reflect as any).getMetadata(JsonNameMetadataKey, target); | ||
const targetClass = Object.getPrototypeOf(retVal); | ||
const metaStore: ClassMetaStore = RootMetaStore.getClassMetaStore(targetClass); | ||
const lateFields: Array<string> = []; | ||
for (const propertyKey of metaStore.getPropertyKeys()) { | ||
const serializeProps = metaStore.getPropertyMeta(propertyKey); | ||
const modelKeys = metaStore.propertyKeys; | ||
for (const propertyKey of modelKeys) { | ||
const serializeProps = metaStore.getMetadataByPropertyKey(propertyKey); | ||
if (serializeProps.isLate) { | ||
@@ -33,3 +34,3 @@ lateFields.push(propertyKey); | ||
for (const propertyKey of lateFields) { | ||
const serializeProps = metaStore.getPropertyMeta(propertyKey); | ||
const serializeProps = metaStore.getMetadataByPropertyKey(propertyKey); | ||
if (serializeProps) { | ||
@@ -36,0 +37,0 @@ const deserialize = serializeProps.deserialize; |
@@ -1,2 +0,2 @@ | ||
import { MetaStore, PropertyMetadata, ParentKey } from './../utils'; | ||
import { ClassMetaStore, ParentKey, PropertyMetadata, RootMetaStore } from './../core'; | ||
@@ -30,3 +30,3 @@ function serializeValue(metadata: PropertyMetadata, value: any, instance: any): any { | ||
* @description Хэлпер для сериализации классов, имеющих поля с навешанным декоратором JsonName. Сериализует только те | ||
* поля, у которых есть декоратор и задано начальное значение. | ||
* поля, у которых есть декоратор и есть значение. | ||
* @param model - экземпляр класса, который надо превратить в данные для отправки серверу по JSONRPC | ||
@@ -37,12 +37,8 @@ * @returns {{}} - обычный объект JS | ||
const result = {}; | ||
const target = Object.getPrototypeOf(model); | ||
const targetClass = Object.getPrototypeOf(model); | ||
const metaStore: MetaStore = MetaStore.getMetaStore(target); | ||
const modelKeys = metaStore.getPropertyKeys(); | ||
const metaStore: ClassMetaStore = RootMetaStore.getClassMetaStore(targetClass); | ||
const modelKeys = metaStore.propertyKeys; | ||
for (const propertyKey of modelKeys) { | ||
if (!metaStore.hasOwnProperty(target, propertyKey)) { | ||
continue; | ||
} | ||
const metadata = metaStore.getPropertyMeta(propertyKey); | ||
const metadata = metaStore.getMetadataByPropertyKey(propertyKey); | ||
const serializedValue = serializeValue(metadata, model[propertyKey], model); | ||
@@ -49,0 +45,0 @@ assignSerializedValueToResult(metadata, serializedValue, result); |
@@ -26,2 +26,3 @@ { | ||
"label-position": true, | ||
"max-classes-per-file": false, | ||
"max-line-length": [true, 140], | ||
@@ -28,0 +29,0 @@ "member-access": false, |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
385413
8
349
47
1326
1