/** * @class JSONSerialiser * * @param {Namespace} namespace * * @property {Namespace} namespace */ class JSONSerialiser { constructor(namespace) { this.namespace = namespace || new this.Namespace(); } /** * @param {Element} element * @returns {object} */ serialise(element) { if (!(element instanceof this.namespace.elements.Element)) { throw new TypeError(`Given element \`${element}\` is not an Element instance`); } const payload = { element: element.element, }; if (element._meta && element._meta.length > 0) { payload.meta = this.serialiseObject(element.meta); } if (element._attributes && element._attributes.length > 0) { payload.attributes = this.serialiseObject(element.attributes); } const content = this.serialiseContent(element.content); if (content !== undefined) { payload.content = content; } return payload; } /** * @param {object} value * @returns {Element} */ deserialise(value) { if (!value.element) { throw new Error('Given value is not an object containing an element name'); } const ElementClass = this.namespace.getElementClass(value.element); const element = new ElementClass(); if (element.element !== value.element) { element.element = value.element; } if (value.meta) { this.deserialiseObject(value.meta, element.meta); } if (value.attributes) { this.deserialiseObject(value.attributes, element.attributes); } const content = this.deserialiseContent(value.content); if (content !== undefined || element.content === null) { element.content = content; } return element; } // Private API serialiseContent(content) { if (content instanceof this.namespace.elements.Element) { return this.serialise(content); } if (content instanceof this.namespace.KeyValuePair) { const pair = { key: this.serialise(content.key), }; if (content.value) { pair.value = this.serialise(content.value); } return pair; } if (content && content.map) { if (content.length === 0) { return undefined; } return content.map(this.serialise, this); } return content; } deserialiseContent(content) { if (content) { if (content.element) { return this.deserialise(content); } if (content.key) { const pair = new this.namespace.KeyValuePair(this.deserialise(content.key)); if (content.value) { pair.value = this.deserialise(content.value); } return pair; } if (content.map) { return content.map(this.deserialise, this); } } return content; } serialiseObject(obj) { const result = {}; obj.forEach((value, key) => { if (value) { result[key.toValue()] = this.serialise(value); } }); if (Object.keys(result).length === 0) { return undefined; } return result; } deserialiseObject(from, to) { Object.keys(from).forEach((key) => { to.set(key, this.deserialise(from[key])); }); } } module.exports = JSONSerialiser;