UNPKG

@dipscope/type-manager

Version:

Transform JSON strings or plain objects into JS class instances.

128 lines 7.32 kB
export class TypeSerializer { serialize(x, serializerContext) { if (x === undefined) { return serializerContext.serializedDefaultValue; } if (x === null) { return serializerContext.serializedNullValue; } if (typeof x === 'object') { return serializerContext.defineReference(x, () => { const type = x; const typeSerializerContext = serializerContext.polymorphic ? serializerContext.definePolymorphicSerializerContext(x.constructor) : serializerContext; const typeState = typeSerializerContext.typeState; const beforeSerializeCallback = typeState.beforeSerializeCallback; if (typeof beforeSerializeCallback === 'string' && typeof type[beforeSerializeCallback] === 'function') { type[beforeSerializeCallback](); } else if (typeof beforeSerializeCallback === 'function') { beforeSerializeCallback(type); } const propertySerializerContext = typeSerializerContext.defineChildSerializerContext(); const object = {}; propertySerializerContext.referenceValueSetter = (v, k) => { const declaringObject = propertySerializerContext.referenceMap.get(type); if (declaringObject !== undefined) { declaringObject[k] = v; } }; for (let i = 0; i < typeState.sortedPropertyMetadatas.length; i++) { const propertyMetadata = typeState.sortedPropertyMetadatas[i]; const propertyState = propertyMetadata.propertyState; if (!propertyState.serializable) { continue; } const serializedPropertyName = propertyState.serializedPropertyName; const deserializedPropertyName = propertyState.deserializedPropertyName; const propertyValue = type[deserializedPropertyName]; propertySerializerContext.jsonPathKey = serializedPropertyName; propertySerializerContext.propertyState = propertyState; propertySerializerContext.typeState = propertyState.typeMetadata.typeState; propertySerializerContext.genericMetadatas = propertyState.genericMetadatas; const serializer = propertySerializerContext.serializer; const value = serializer.serialize(propertyValue, propertySerializerContext); object[serializedPropertyName] = value; } if (typeState.preserveDiscriminator) { object[typeState.discriminator] = typeState.discriminant; } else if (object.hasOwnProperty(typeState.discriminator)) { delete object[typeState.discriminator]; } return object; }); } serializerContext.logger.error('TypeSerializer', `${serializerContext.jsonPath}: cannot serialize value as type.`, x); return undefined; } deserialize(x, serializerContext) { if (x === undefined) { return serializerContext.deserializedDefaultValue; } if (x === null) { return serializerContext.deserializedNullValue; } if (typeof x === 'object') { return serializerContext.restoreReference(x, () => { const object = x; const typeSerializerContext = serializerContext.polymorphic ? serializerContext.definePolymorphicSerializerContext(x) : serializerContext; const propertySerializerContext = typeSerializerContext.defineChildSerializerContext(); const typeState = typeSerializerContext.typeState; const typeEntryMap = new Map(); propertySerializerContext.referenceValueSetter = (v, k) => { const declaringType = propertySerializerContext.referenceMap.get(object); if (declaringType !== undefined) { declaringType[k] = v; } }; for (let i = 0; i < typeState.sortedPropertyMetadatas.length; i++) { const propertyMetadata = typeState.sortedPropertyMetadatas[i]; const propertyState = propertyMetadata.propertyState; if (!propertyState.deserializable) { continue; } const serializedPropertyName = propertyState.serializedPropertyName; const deserializedPropertyName = propertyState.deserializedPropertyName; const propertyValue = object[serializedPropertyName]; propertySerializerContext.jsonPathKey = serializedPropertyName; propertySerializerContext.propertyState = propertyState; propertySerializerContext.typeState = propertyState.typeMetadata.typeState; propertySerializerContext.genericMetadatas = propertyState.genericMetadatas; const serializer = propertySerializerContext.serializer; const value = serializer.deserialize(propertyValue, propertySerializerContext); typeEntryMap.set(deserializedPropertyName, { key: deserializedPropertyName, value: value, propertyMetadata: propertyMetadata }); typeEntryMap.set(serializedPropertyName, { key: serializedPropertyName, value: value, propertyMetadata: propertyMetadata }); } for (const propertyName in object) { if (object.hasOwnProperty(propertyName) && !typeEntryMap.has(propertyName)) { typeEntryMap.set(propertyName, { key: propertyName, value: object[propertyName] }); } } const factory = typeState.factory; const injector = typeState.injector; const type = factory.build(typeState.typeMetadata, typeEntryMap, injector); if (typeState.preserveDiscriminator) { type[typeState.discriminator] = typeState.discriminant; } else if (type.hasOwnProperty(typeState.discriminator)) { delete type[typeState.discriminator]; } const afterDeserializeCallback = typeState.afterDeserializeCallback; if (typeof afterDeserializeCallback === 'string' && typeof type[afterDeserializeCallback] === 'function') { type[afterDeserializeCallback](); } else if (typeof afterDeserializeCallback === 'function') { afterDeserializeCallback(type); } return type; }); } serializerContext.logger.error('TypeSerializer', `${serializerContext.jsonPath}: cannot deserialize value as type.`, x); return undefined; } } //# sourceMappingURL=type-serializer.js.map