Socket
Socket
Sign inDemoInstall

typescript-json-serializer

Package Overview
Dependencies
2
Maintainers
1
Versions
61
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 3.4.5 to 4.0.0

dist/helpers.d.ts

36

CHANGELOG.md

@@ -0,1 +1,37 @@

<a name="4.0.0"></a>
# 4.0.0 (2022-02-15)
New major version comes with lot of breaking changes detailed below.
The purpose was to reorganize the entire project, write more tests and above all improve the usage of the library.
Check the new [README](./README.md) to understand how to use `typescript-json-serializer` now.
### BREAKING CHANGES
- `Serializable`:
- the decorator was renamed to `JsonObject` to be more consistent
- `formatPropertyNames` option has been moved to the new `JsonSerializerOptions` class.
- `JsonProperty`:
- `predicate` argument has been removed, now you can use the `type` argument
- `names` argument has been removed, now you can use the `name` argument
- `serialize` function has been moved to the new `JsonSerializer` class
- `deserialize` function has been moved to the new `JsonSerializer` class
### Build
- replace `tsc` by `rollup` for types generation ([ca9f08](https://github.com/GillianPerard/typescript-json-serializer/commit/ca9f0829f557caeb35442abbd3169944edb71ceb))
- bump `tmpl` from version 1.0.4 to 1.0.5
### Features
- **JsonSerializer**: new class was added to handle all the logic about serialization and deserialization ([bcc49e](https://github.com/GillianPerard/typescript-json-serializer/commit/bcc49e118e21d37f332dc6657ab94b8e25564b05))
- **JsonSerializerOptions**: new class was added to handle all the `JsonSerializer` options as ([bcc49e](https://github.com/GillianPerard/typescript-json-serializer/commit/bcc49e118e21d37f332dc6657ab94b8e25564b05))
- **errorCallback**: callback you can define to handle the errors, by default the library comes with 2 predefined callback `logError` and `throwError` but you can define your own
- **nullishPolicy**: object to define what is the policy when the algorithm meet a `null` or an `undefined` value, the 3 choices are `allow`, `disallow` and `remove`
- **formatPropertyName**: this option has been moved from `Serializable` decorator and keep the same behavior
- **serializeObject**: new method added to `JsonSerializer` to serialize object only ([bcc49e](https://github.com/GillianPerard/typescript-json-serializer/commit/bcc49e118e21d37f332dc6657ab94b8e25564b05))
- **serializeObjectArray**: new method added to `JsonSerializer` to serialize object object array only ([bcc49e](https://github.com/GillianPerard/typescript-json-serializer/commit/bcc49e118e21d37f332dc6657ab94b8e25564b05))
- **deserializeObject**: new method added to `JsonSerializer` to deserialize object only ([bcc49e](https://github.com/GillianPerard/typescript-json-serializer/commit/bcc49e118e21d37f332dc6657ab94b8e25564b05))
- **deserializeObjectArray**: new method added to `JsonSerializer` to deserialize object object array only ([bcc49e](https://github.com/GillianPerard/typescript-json-serializer/commit/bcc49e118e21d37f332dc6657ab94b8e25564b05))
<a name="3.4.5"></a>

@@ -2,0 +38,0 @@ # 3.4.5 (2022-01-07)

2

dist/index.cjs.js

@@ -1,1 +0,1 @@

"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("tslib");require("reflect-metadata");var r,t="api:map:";!function(e){e.Array="array",e.Boolean="boolean",e.Date="date",e.Number="number",e.Object="object",e.String="string"}(r||(r={}));var a=function(r){var t=Reflect.getPrototypeOf(r);return t&&t.name?e.__spreadArray(e.__spreadArray([],a(t)),[t.name]):[]},n=function(e,r){return e.map((function(e){return Reflect.getMetadata(""+t+e,r)}))},i=function(){for(var r=[],t=0;t<arguments.length;t++)r[t]=arguments[t];var a={};return r.forEach((function(r){r&&Object.keys(r).forEach((function(t){a[t]=e.__assign(e.__assign({},a[t]),r[t])}))})),a},o=function(a,o){var s;if([null,void 0].includes(a))return a;if(void 0===o)return p(typeof a,a);typeof a===r.String&&(a=JSON.parse(a));var c=new o({}),u=c.constructor.name,l=null!==(s=Reflect.getMetadata("api:map:serializable",o))&&void 0!==s?s:{},d=l.baseClassNames,v=l.options,y=""+t+u,m=Reflect.hasMetadata(y,c),g={};if(!(m||d&&d.length))return c;if(g=Reflect.getMetadata(y,c),d&&d.length){var b=n(d,c);g=i.apply(void 0,e.__spreadArray(e.__spreadArray([],b),[g]))}return Object.keys(g).forEach((function(e){var r=f(c,e,g[e],a,null==v?void 0:v.formatPropertyNames);if(null==r&&g[e].required)throw new Error("Property '"+e+"' is required in "+u+" "+JSON.stringify(a)+".");void 0!==r&&(c[e]=r)})),c},s=function(a,o){var s;if(void 0===o&&(o=!0),[void 0,null].includes(a)||typeof a!==r.Object)return a;var f=a.constructor.name,u=""+t+f,l=null!==(s=Reflect.getMetadata("api:map:serializable",a.constructor))&&void 0!==s?s:{},p=l.baseClassNames,d=l.options,v=p&&p.length,y=Reflect.hasMetadata(u,a),m={};if(!y&&!v)return a;if(m=Reflect.getMetadata(u,a),v){var g=n(p,a);m=i.apply(void 0,e.__spreadArray(e.__spreadArray([],g),[m]))}var b={},O=Object.keys(a);return Object.keys(m).forEach((function(e){if(O.includes(e)){var r=m[e],t=r.beforeSerialize,n=r.afterSerialize,i=void 0;t&&(i=a[e],a[e]=t(a[e],a));var s=c(a,e,r,o);if(n&&(s=n(s,a)),a[e]=i||a[e],r.names)r.names.forEach((function(e){(!o||o&&void 0!==s[e])&&(b[e]=s[e])}));else if(!o||o&&void 0!==s)if(!r.isNameOverridden&&(null==d?void 0:d.formatPropertyNames)){var f=d.formatPropertyNames(r.name);b[f]=s}else b[r.name]=s}})),b},c=function(e,t,a,n){var i=e[t],o=Reflect.getMetadata("design:type",e,t),c=!!o.name&&o.name.toLocaleLowerCase()===r.Array,f=a.predicate,l=a.type||o,p=u(l);if(i&&(p||f)){if(c)return i.map((function(e){return s(e,n)}));if(a.isDictionary){var d={};return Object.keys(i).forEach((function(e){d[e]=s(i[e],n)})),d}return s(i,n)}return l.name.toLocaleLowerCase()===r.Date&&typeof i===r.Object?i.toISOString():i},f=function(e,t,a,n,i){var s;if([null,void 0].includes(n))return n;if("names"in a){var c={};a.names.forEach((function(e){return c[e]=n[e]})),s=c}else if("name"in a&&!a.isNameOverridden&&i){var f=i(a.name);s=n[f]}else s=n[a.name];if([null,void 0].includes(s))return s;var l,d=Reflect.getMetadata("design:type",e,t),v=!!d.name&&d.name.toLowerCase()===r.Array,y=a.isDictionary,m=a.predicate,g=a.beforeDeserialize,b=a.afterDeserialize,O=a.type||d,h=u(O);if(g&&(s=g(s,e)),y){var N={};typeof s!==r.Object?(console.error("Type '"+typeof s+"' is not assignable to type 'Dictionary' for property '"+t+"' in '"+e.constructor.name+"'.\n","Received: "+JSON.stringify(s)),l=void 0):(Object.keys(s).forEach((function(r){h||m?(m&&(O=m(s[r],s)),N[r]=o(s[r],O)):N[r]=p(typeof s[r],s[r],t,e.constructor.name)})),l=N)}else if(v){var S=[];Array.isArray(s)?(s.forEach((function(r){h||m?(m&&(O=m(r,s)),S.push(o(r,O))):S.push(p(typeof r,r,t,e.constructor.name))})),l=S):(console.error("Type '"+typeof s+"' is not assignable to type 'Array' for property '"+t+"' in '"+e.constructor.name+"'.\n","Received: "+JSON.stringify(s)),l=void 0)}else h||m?(O=m?m(s,n):O,l=o(s,O)):l=p(O.name,s,t,e.constructor.name);return b&&(l=b(l,e)),l},u=function(e){return Reflect.hasOwnMetadata("api:map:serializable",e)},l=function(e,t){if(!t)return{name:e.toString(),isNameOverridden:!1};var a;a=typeof t===r.String?{name:t,isNameOverridden:!0}:t.name?{name:t.name,isNameOverridden:!0}:t.names&&t.names.length?{names:t.names}:{name:e.toString(),isNameOverridden:!1};return["isDictionary","required","beforeSerialize","afterSerialize","beforeDeserialize","afterDeserialize"].forEach((function(e){void 0!==t[e]&&null!==t[e]&&(a[e]=t[e])})),t.predicate?a.predicate=t.predicate:t.type&&(a.type=t.type),a},p=function(e,t,a,n){if(null==e)return t;if(e=e.toLowerCase(),(typeof t).toLowerCase()===e)return t;var i=function(){console.error("Type '"+typeof t+"' is not assignable to type '"+e+"' for property '"+a+"' in '"+n+"'.\n","Received: "+JSON.stringify(t))};switch(e){case r.String:var o=t.toString();return"[object Object]"===o?void i():o;case r.Number:var s=+t;return isNaN(s)?void i():s;case r.Boolean:return void i();case r.Date:return isNaN(Date.parse(t))?void i():new Date(t);default:return t}};exports.JsonProperty=function(e){return function(r,a,n){if(void 0===a&&r.prototype){var i=Reflect.getMetadata("design:paramtypes",r)[n];a=function(e){var r=e.toString().split("}")[0].replace(/(\/\*[\s\S]*?\*\/|\/\/.*$)/gm,"").replace(/[\r\t\n\v\f ]/g,""),t=/(?:this\.)([^,;\n}]+)/gm,a=new Map,n=/(?:.*(?:constructor|function).*?(?=\())(?:\()(.+?(?=\)))/m.exec(r);if(!n||!n.length)return a;for(var i,o=n[1].split(","),s=function(){var e=i[1].split("="),r=o.findIndex((function(r){return r===e[1]}));r>-1&&a.set(r,e[0])};i=t.exec(r);)s();return a}(r.prototype.constructor).get(n),r=r.prototype,Reflect.defineMetadata("design:type",i,r,a)}var o={},s=r.constructor.name,c=""+t+s;Reflect.hasMetadata(c,r)&&(o=Reflect.getMetadata(c,r)),o[a]=l(a,e),Reflect.defineMetadata(c,o,r)}},exports.Serializable=function(e){return function(r){var t=a(r);Reflect.defineMetadata("api:map:serializable",{baseClassNames:t,options:e},r)}},exports.deserialize=o,exports.serialize=s;
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("tslib");require("reflect-metadata");var t=function(){function e(){}return e.getBaseClass=function(e){return e?Reflect.getPrototypeOf(e):void 0},e.getJsonPropertiesMetadata=function(t,r){if(t){var i=""+e.apiMap+(r||t.constructor.name);return Reflect.getMetadata(i,t)}},e.getParamTypes=function(t){return t?Reflect.getMetadata(e.designParamTypes,t):void 0},e.getJsonObjectMetadata=function(t){return t?Reflect.getMetadata(e.apiMapJsonObject,t):void 0},e.getType=function(t,r){return t?Reflect.getMetadata(e.designType,t,r):void 0},e.isJsonObject=function(t){return!!t&&Reflect.hasOwnMetadata(e.apiMapJsonObject,t)},e.setJsonPropertiesMetadata=function(t,r){if(r){var i=""+e.apiMap+r.constructor.name;Reflect.defineMetadata(i,t,r)}},e.setJsonObject=function(t,r){r&&Reflect.defineMetadata(e.apiMapJsonObject,t,r)},e.setType=function(t,r,i){r&&t&&Reflect.defineMetadata(e.designType,t,r,i)},e.apiMap="api:map:",e.apiMapJsonObject=e.apiMap+"jsonObject",e.designType="design:type",e.designParamTypes="design:paramtypes",e}(),r=function(e){return"string"==typeof e},i=function(e){return null!==e&&"object"==typeof e&&!n(e)},n=function(e){return Array.isArray(e)},o=function(e){return"[object Date]"===toString.call(e)},a=function(e){return[null,void 0].includes(e)},s=function(e){return t.isJsonObject(e)},l=function(e){try{var t=JSON.parse(e);return"object"==typeof t?t:e}catch(t){return e}},u=function(){this.errorCallback=c,this.nullishPolicy={undefined:"remove",null:"allow"}},c=function(e){console.error(e)},p=function(){function c(t){this.options=new u,this.options=e.__assign(e.__assign({},this.options),t)}return c.prototype.deserialize=function(e,t){return r(e)&&(e=l(e)),n(e)?this.deserializeObjectArray(e,t):i(e)?this.deserializeObject(e,t):void this.error("Fail to deserialize: value is not an Array nor an Object.\nReceived: "+JSON.stringify(e)+".")},c.prototype.deserializeObject=function(e,t){var n=this;if(null===e)return"disallow"===this.options.nullishPolicy.null&&this.error("Fail to deserialize: null is not assignable to type Object."),null;if(void 0!==e){if(r(e)&&(e=l(e)),i(e)){var o=new t({}),s=this.getJsonPropertiesMetadata(o);return s?(Object.keys(s).forEach((function(t){var r=s[t],i=n.deserializeProperty(o,t,e,r);if(r.required&&a(i)){var l=o.constructor.name;n.error("Property '"+t+"' is required in "+l+" "+JSON.stringify(e)+".")}n.isAllowedProperty(i)&&(o[t]=i)})),o):o}this.error("Fail to deserialize: type '"+typeof e+"' is not assignable to type 'Object'.\nReceived: "+JSON.stringify(e))}else"disallow"===this.options.nullishPolicy.undefined&&this.error("Fail to deserialize: undefined is not assignable to type Object.")},c.prototype.deserializeObjectArray=function(e,t){var i=this;if(null===e)return"disallow"===this.options.nullishPolicy.null&&this.error("Fail to deserialize: null is not assignable to type Array."),null;if(void 0!==e){if(r(e)&&(e=l(e)),n(e))return e.map((function(e){return i.deserializeObject(e,t)}));this.error("Fail to deserialize: type '"+typeof e+"' is not assignable to type 'Array'.\nReceived: "+JSON.stringify(e))}else"disallow"===this.options.nullishPolicy.undefined&&this.error("Fail to deserialize: undefined is not assignable to type Array.")},c.prototype.serialize=function(e){return n(e)?this.serializeObjectArray(e):i(e)?this.serializeObject(e):void this.error("Fail to serialize: value is not an Array nor an Object.\nReceived: "+JSON.stringify(e)+".")},c.prototype.serializeObject=function(e){var t=this;if(null===e)return"disallow"===this.options.nullishPolicy.null&&this.error("Fail to serialize: null is not assignable to type Object."),null;if(void 0!==e){if(!i(e))return e;var r=this.getJsonPropertiesMetadata(e);if(!r)return e;var o={},a=Object.keys(e);return Object.keys(r).forEach((function(i){if(a.includes(i)){var s=r[i],l=void 0;s.beforeSerialize&&(l=e[i],e[i]=s.beforeSerialize(e[i],e));var u=t.serializeProperty(e,i,s);if(s.afterSerialize&&(u=s.afterSerialize(u,e)),e[i]=l||e[i],n(s.name))s.name.forEach((function(e){t.isAllowedProperty(u[e])&&(o[e]=u[e])}));else if(t.isAllowedProperty(u))if(s.isNameOverridden||void 0===t.options.formatPropertyName)o[s.name]=u;else{var c=t.options.formatPropertyName(s.name);o[c]=u}}})),o}"disallow"===this.options.nullishPolicy.undefined&&this.error("Fail to serialize: undefined is not assignable to type Object.")},c.prototype.serializeObjectArray=function(e){var t=this;if(null===e)return"disallow"===this.options.nullishPolicy.null&&this.error("Fail to serialize: null is not assignable to type Array."),null;if(void 0!==e){if(n(e))return e.map((function(e){return t.serializeObject(e)}));this.error("Fail to serialize: type '"+typeof e+"' is not assignable to type 'Array'.\nReceived: "+JSON.stringify(e)+".")}else"disallow"===this.options.nullishPolicy.undefined&&this.error("Fail to serialize: undefined is not assignable to type Array.")},c.prototype.deserializeProperty=function(e,r,i,n){var o;if(!a(i)){var l=this.getDataSource(i,n,this.options.formatPropertyName);if(a(l))return l;var u,c=t.getType(e,r),p="array"===(null===(o=null==c?void 0:c.name)||void 0===o?void 0:o.toLowerCase()),f=n.type||c;n.beforeDeserialize&&(l=n.beforeDeserialize(l,e));var d=n.predicate;return n.isDictionary?u=this.deserializeDictionary(l,f,d):p?u=this.deserializeArray(l,f,d):!s(f)&&!d||d&&!d(l,i)?u=this.deserializePrimitive(l,f.name):(f=n.predicate?n.predicate(l,i):f,u=this.deserializeObject(l,f)),n.afterDeserialize&&(u=n.afterDeserialize(u,e)),u}},c.prototype.deserializePrimitive=function(e,t){if(a(t))return e;if(typeof e===(t=t.toLowerCase()))return e;var r="Fail to deserialize: type '"+typeof e+"' is not assignable to type '"+t+"'.\nReceived: "+JSON.stringify(e);switch(t){case"string":var i=e.toString();return"[object Object]"===i?void this.error(r):i;case"number":return function(e){return"number"==typeof e}(e)?+e:void this.error(r);case"boolean":return void this.error(r);case"date":return function(e){return!o(e)&&!n(e)&&!isNaN(Date.parse(e))}(e)?new Date(e):void this.error(r);default:return e}},c.prototype.deserializeDictionary=function(e,t,r){var n=this;if(i(e)){var o={};return Object.keys(e).forEach((function(i){var a=r?r(e[i],e):void 0;s(t)||a?o[i]=n.deserializeObject(e[i],a||t):o[i]=n.deserializePrimitive(e[i],typeof e[i])})),o}this.error("Fail to deserialize: type '"+typeof e+"' is not assignable to type 'Dictionary'.\nReceived: "+JSON.stringify(e)+".")},c.prototype.deserializeArray=function(e,t,r){var i=this;if(n(e))return e.map((function(n){return s(t)||r?(t=r?r(n,e):t,i.deserializeObject(n,t)):i.deserializePrimitive(n,typeof n)}));this.error("Fail to deserialize: type '"+typeof e+"' is not assignable to type 'Array'.\nReceived: "+JSON.stringify(e))},c.prototype.error=function(e){this.options.errorCallback&&this.options.errorCallback(e)},c.prototype.getClassesJsonPropertiesMetadata=function(e,r){return e?e.reduce((function(e,i){var n=t.getJsonPropertiesMetadata(r,i);return n&&e.push(n),e}),[]):[]},c.prototype.getDataSource=function(e,t,r){var i=t.name,o=t.isNameOverridden;if(n(i)){var a={};return i.forEach((function(t){return a[t]=e[t]})),a}return!o&&r?(i=r(i),e[i]):e[i]},c.prototype.getJsonPropertiesMetadata=function(r){var i,n=(null!==(i=t.getJsonObjectMetadata(r.constructor))&&void 0!==i?i:{}).baseClassNames,o=t.getJsonPropertiesMetadata(r);if(!(o||n&&n.length))return o;if(n&&n.length){var a=this.getClassesJsonPropertiesMetadata(n,r);return this.mergeJsonPropertiesMetadata.apply(this,e.__spreadArray(e.__spreadArray([],a),[o]))}return o},c.prototype.isAllowedProperty=function(e){if(a(e)){if("disallow"===this.options.nullishPolicy[""+e])return this.error("Disallowed "+e+" value detected."),!1;if("remove"===this.options.nullishPolicy[""+e])return!1}return!0},c.prototype.mergeJsonPropertiesMetadata=function(){for(var t=[],r=0;r<arguments.length;r++)t[r]=arguments[r];var i={};return t.forEach((function(t){t&&Object.keys(t).forEach((function(r){i[r]=e.__assign(e.__assign({},i[r]),t[r])}))})),i},c.prototype.serializeDictionary=function(e){var t=this;if(i(e)){var r={};return Object.keys(e).forEach((function(i){r[i]=t.serializeObject(e[i])})),r}this.error("Fail to serialize: type '"+typeof e+"' is not assignable to type 'Dictionary'.\nReceived: "+JSON.stringify(e)+".")},c.prototype.serializeProperty=function(e,r,i){var n,a,l=e[r],u=t.getType(e,r),c="array"===(null===(n=null==u?void 0:u.name)||void 0===n?void 0:n.toLocaleLowerCase()),p=i.predicate,f=i.type||u,d=s(f);return l&&(d||p)?c?this.serializeObjectArray(l):i.isDictionary?this.serializeDictionary(l):this.serializeObject(l):"date"===(null===(a=null==f?void 0:f.name)||void 0===a?void 0:a.toLocaleLowerCase())&&o(l)?l.toISOString():l},c}(),f=function(r){var i=t.getBaseClass(r);return i&&i.name?e.__spreadArray(e.__spreadArray([],f(i)),[i.name]):[]},d=function(e){var t,r=e.toString().split("}")[0].replace(/(\/\*[\s\S]*?\*\/|\/\/.*$)/gm,"").replace(/[\r\t\n\v\f ]/g,""),i=r.length;","===r[i-2]&&(t=r[i-1]);var n=t?new RegExp("(?:(this|"+t+"|\\("+t+"=t.call\\(this(,.)*\\)\\))\\.)([^,;\n}]+)","gm"):new RegExp("(?:(this)\\.)([^,;\n}]+)","gm"),o=new Map,a=/(?:.*(?:constructor|function).*?(?=\())(?:\()(.+?(?=\)))/m.exec(r);if(!a||!a.length)return o;for(var s,l=a[1].split(","),u=function(){var e=s.length-1,t=s[e].split("="),r=l.findIndex((function(e){return e===t[1]}));r>-1&&o.set(r,t[0])};s=n.exec(r);)u();return o},y=function(n,o){var a={name:n.toString()};return o?r(o)?(a.name=o,a.isNameOverridden=!0,a):(i(o)&&(a=e.__assign(e.__assign({},a),o),o.name&&(a.name=o.name,a.isNameOverridden=!0),function(e){if(!e)return!1;var r=t.getParamTypes(e),i=e.length;return(1===i||2===i)&&!r}(o.type)&&(delete a.type,a.predicate=o.type)),a):a};exports.JsonObject=function(){return function(e){var r=f(e);t.setJsonObject({baseClassNames:r},e)}},exports.JsonProperty=function(e){return function(r,i,n){var o;if(void 0===i&&r.prototype){var a=t.getParamTypes(r)[n];i=d(r.prototype.constructor).get(n),r=r.prototype,t.setType(a,r,i)}var s=null!==(o=t.getJsonPropertiesMetadata(r))&&void 0!==o?o:{};s[i]=y(i,e),t.setJsonPropertiesMetadata(s,r)}},exports.JsonSerializer=p,exports.JsonSerializerOptions=u,exports.logError=c,exports.throwError=function(e){throw new Error(e)};

@@ -1,62 +0,4 @@

import 'reflect-metadata';
interface SerializableOptions {
formatPropertyNames: FormatPropertyNameProto;
}
declare type IOProto = (property: any, currentInstance?: any) => any;
declare type PredicateProto = (property: any, parentProperty?: any) => any;
declare type FormatPropertyNameProto = (propertyName: string) => string;
interface BeforeAfterProto {
beforeSerialize?: IOProto;
afterSerialize?: IOProto;
beforeDeserialize?: IOProto;
afterDeserialize?: IOProto;
}
declare type BaseMetadata = {
required?: boolean;
} & BeforeAfterProto;
declare type Args = string | ({
name?: string;
type?: Function;
isDictionary?: boolean;
} & BaseMetadata) | ({
name?: string;
predicate?: PredicateProto;
isDictionary?: boolean;
} & BaseMetadata) | ({
names: Array<string>;
type?: Function;
} & BaseMetadata) | ({
names: Array<string>;
predicate?: PredicateProto;
} & BaseMetadata);
/**
* Decorator to take the property in account during the serialize and deserialize function
*
* @param {Args=} args Arguments to describe the property
*/
export declare const JsonProperty: (args?: Args) => Function;
/**
* Decorator to make a class Serializable
*
* @param {{formatPropertyNames: FormatPropertyNameProto}=} options The options of the serializable class
*
* BREAKING CHANGE: Since version 2.0.0 the parameter `baseClassName` is not needed anymore
*/
export declare const Serializable: (options?: SerializableOptions) => Function;
/**
* Function to deserialize json into a class
*
* @param {object} json The json to deserialize
* @param {new (...params: Array<any>) => T} type The class in which we want to deserialize
* @returns {T} The instance of the specified type containing all deserialized properties
*/
export declare const deserialize: <T>(json: any, type: new (...params: Array<any>) => T) => T;
/**
* Function to serialize a class into json
*
* @param {any} instance Instance of the object to deserialize
* @param {boolean} removeUndefined Indicates if you want to keep or remove undefined values
* @returns {any} The json object
*/
export declare const serialize: (instance: any, removeUndefined?: boolean) => any;
export {};
export { JsonSerializer } from './json-serializer';
export { ErrorCallback, FormatPropertyNameProto, JsonSerializerOptions, NullishPolicy, Policy, logError, throwError } from './json-serializer-options';
export { JsonObject, JsonObjectMetadata } from './json-object';
export { JsonProperty } from './json-property';

@@ -1,1 +0,1 @@

import{__spreadArray as e,__assign as t}from"tslib";import"reflect-metadata";var r,a="api:map:";!function(e){e.Array="array",e.Boolean="boolean",e.Date="date",e.Number="number",e.Object="object",e.String="string"}(r||(r={}));var n=function(t){var r=Reflect.getPrototypeOf(t);return r&&r.name?e(e([],n(r)),[r.name]):[]},i=function(e){return function(t,r,n){if(void 0===r&&t.prototype){var i=Reflect.getMetadata("design:paramtypes",t)[n];r=function(e){var t=e.toString().split("}")[0].replace(/(\/\*[\s\S]*?\*\/|\/\/.*$)/gm,"").replace(/[\r\t\n\v\f ]/g,""),r=/(?:this\.)([^,;\n}]+)/gm,a=new Map,n=/(?:.*(?:constructor|function).*?(?=\())(?:\()(.+?(?=\)))/m.exec(t);if(!n||!n.length)return a;for(var i,o=n[1].split(","),c=function(){var e=i[1].split("="),t=o.findIndex((function(t){return t===e[1]}));t>-1&&a.set(t,e[0])};i=r.exec(t);)c();return a}(t.prototype.constructor).get(n),t=t.prototype,Reflect.defineMetadata("design:type",i,t,r)}var o={},c=t.constructor.name,f=""+a+c;Reflect.hasMetadata(f,t)&&(o=Reflect.getMetadata(f,t)),o[r]=m(r,e),Reflect.defineMetadata(f,o,t)}},o=function(e){return function(t){var r=n(t);Reflect.defineMetadata("api:map:serializable",{baseClassNames:r,options:e},t)}},c=function(e,t){return e.map((function(e){return Reflect.getMetadata(""+a+e,t)}))},f=function(){for(var e=[],r=0;r<arguments.length;r++)e[r]=arguments[r];var a={};return e.forEach((function(e){e&&Object.keys(e).forEach((function(r){a[r]=t(t({},a[r]),e[r])}))})),a},s=function(t,n){var i;if([null,void 0].includes(t))return t;if(void 0===n)return v(typeof t,t);typeof t===r.String&&(t=JSON.parse(t));var o=new n({}),s=o.constructor.name,u=null!==(i=Reflect.getMetadata("api:map:serializable",n))&&void 0!==i?i:{},l=u.baseClassNames,d=u.options,m=""+a+s,y=Reflect.hasMetadata(m,o),g={};if(!(y||l&&l.length))return o;if(g=Reflect.getMetadata(m,o),l&&l.length){var b=c(l,o);g=f.apply(void 0,e(e([],b),[g]))}return Object.keys(g).forEach((function(e){var r=p(o,e,g[e],t,null==d?void 0:d.formatPropertyNames);if(null==r&&g[e].required)throw new Error("Property '"+e+"' is required in "+s+" "+JSON.stringify(t)+".");void 0!==r&&(o[e]=r)})),o},u=function(t,n){var i;if(void 0===n&&(n=!0),[void 0,null].includes(t)||typeof t!==r.Object)return t;var o=t.constructor.name,s=""+a+o,u=null!==(i=Reflect.getMetadata("api:map:serializable",t.constructor))&&void 0!==i?i:{},p=u.baseClassNames,d=u.options,m=p&&p.length,v=Reflect.hasMetadata(s,t),y={};if(!v&&!m)return t;if(y=Reflect.getMetadata(s,t),m){var g=c(p,t);y=f.apply(void 0,e(e([],g),[y]))}var b={},h=Object.keys(t);return Object.keys(y).forEach((function(e){if(h.includes(e)){var r=y[e],a=r.beforeSerialize,i=r.afterSerialize,o=void 0;a&&(o=t[e],t[e]=a(t[e],t));var c=l(t,e,r,n);if(i&&(c=i(c,t)),t[e]=o||t[e],r.names)r.names.forEach((function(e){(!n||n&&void 0!==c[e])&&(b[e]=c[e])}));else if(!n||n&&void 0!==c)if(!r.isNameOverridden&&(null==d?void 0:d.formatPropertyNames)){var f=d.formatPropertyNames(r.name);b[f]=c}else b[r.name]=c}})),b},l=function(e,t,a,n){var i=e[t],o=Reflect.getMetadata("design:type",e,t),c=!!o.name&&o.name.toLocaleLowerCase()===r.Array,f=a.predicate,s=a.type||o,l=d(s);if(i&&(l||f)){if(c)return i.map((function(e){return u(e,n)}));if(a.isDictionary){var p={};return Object.keys(i).forEach((function(e){p[e]=u(i[e],n)})),p}return u(i,n)}return s.name.toLocaleLowerCase()===r.Date&&typeof i===r.Object?i.toISOString():i},p=function(e,t,a,n,i){var o;if([null,void 0].includes(n))return n;if("names"in a){var c={};a.names.forEach((function(e){return c[e]=n[e]})),o=c}else if("name"in a&&!a.isNameOverridden&&i){var f=i(a.name);o=n[f]}else o=n[a.name];if([null,void 0].includes(o))return o;var u,l=Reflect.getMetadata("design:type",e,t),p=!!l.name&&l.name.toLowerCase()===r.Array,m=a.isDictionary,y=a.predicate,g=a.beforeDeserialize,b=a.afterDeserialize,h=a.type||l,O=d(h);if(g&&(o=g(o,e)),m){var N={};typeof o!==r.Object?(console.error("Type '"+typeof o+"' is not assignable to type 'Dictionary' for property '"+t+"' in '"+e.constructor.name+"'.\n","Received: "+JSON.stringify(o)),u=void 0):(Object.keys(o).forEach((function(r){O||y?(y&&(h=y(o[r],o)),N[r]=s(o[r],h)):N[r]=v(typeof o[r],o[r],t,e.constructor.name)})),u=N)}else if(p){var R=[];Array.isArray(o)?(o.forEach((function(r){O||y?(y&&(h=y(r,o)),R.push(s(r,h))):R.push(v(typeof r,r,t,e.constructor.name))})),u=R):(console.error("Type '"+typeof o+"' is not assignable to type 'Array' for property '"+t+"' in '"+e.constructor.name+"'.\n","Received: "+JSON.stringify(o)),u=void 0)}else O||y?(h=y?y(o,n):h,u=s(o,h)):u=v(h.name,o,t,e.constructor.name);return b&&(u=b(u,e)),u},d=function(e){return Reflect.hasOwnMetadata("api:map:serializable",e)},m=function(e,t){if(!t)return{name:e.toString(),isNameOverridden:!1};var a;a=typeof t===r.String?{name:t,isNameOverridden:!0}:t.name?{name:t.name,isNameOverridden:!0}:t.names&&t.names.length?{names:t.names}:{name:e.toString(),isNameOverridden:!1};return["isDictionary","required","beforeSerialize","afterSerialize","beforeDeserialize","afterDeserialize"].forEach((function(e){void 0!==t[e]&&null!==t[e]&&(a[e]=t[e])})),t.predicate?a.predicate=t.predicate:t.type&&(a.type=t.type),a},v=function(e,t,a,n){if(null==e)return t;if(e=e.toLowerCase(),(typeof t).toLowerCase()===e)return t;var i=function(){console.error("Type '"+typeof t+"' is not assignable to type '"+e+"' for property '"+a+"' in '"+n+"'.\n","Received: "+JSON.stringify(t))};switch(e){case r.String:var o=t.toString();return"[object Object]"===o?void i():o;case r.Number:var c=+t;return isNaN(c)?void i():c;case r.Boolean:return void i();case r.Date:return isNaN(Date.parse(t))?void i():new Date(t);default:return t}};export{i as JsonProperty,o as Serializable,s as deserialize,u as serialize};
import{__spreadArray as e,__assign as t}from"tslib";import"reflect-metadata";var i=function(){function e(){}return e.getBaseClass=function(e){return e?Reflect.getPrototypeOf(e):void 0},e.getJsonPropertiesMetadata=function(t,i){if(t){var r=""+e.apiMap+(i||t.constructor.name);return Reflect.getMetadata(r,t)}},e.getParamTypes=function(t){return t?Reflect.getMetadata(e.designParamTypes,t):void 0},e.getJsonObjectMetadata=function(t){return t?Reflect.getMetadata(e.apiMapJsonObject,t):void 0},e.getType=function(t,i){return t?Reflect.getMetadata(e.designType,t,i):void 0},e.isJsonObject=function(t){return!!t&&Reflect.hasOwnMetadata(e.apiMapJsonObject,t)},e.setJsonPropertiesMetadata=function(t,i){if(i){var r=""+e.apiMap+i.constructor.name;Reflect.defineMetadata(r,t,i)}},e.setJsonObject=function(t,i){i&&Reflect.defineMetadata(e.apiMapJsonObject,t,i)},e.setType=function(t,i,r){i&&t&&Reflect.defineMetadata(e.designType,t,i,r)},e.apiMap="api:map:",e.apiMapJsonObject=e.apiMap+"jsonObject",e.designType="design:type",e.designParamTypes="design:paramtypes",e}(),r=function(e){return"string"==typeof e},n=function(e){return null!==e&&"object"==typeof e&&!o(e)},o=function(e){return Array.isArray(e)},a=function(e){return"[object Date]"===toString.call(e)},s=function(e){return[null,void 0].includes(e)},l=function(e){return i.isJsonObject(e)},u=function(e){try{var t=JSON.parse(e);return"object"==typeof t?t:e}catch(t){return e}},c=function(){this.errorCallback=f,this.nullishPolicy={undefined:"remove",null:"allow"}},p=function(e){throw new Error(e)},f=function(e){console.error(e)},d=function(){function p(e){this.options=new c,this.options=t(t({},this.options),e)}return p.prototype.deserialize=function(e,t){return r(e)&&(e=u(e)),o(e)?this.deserializeObjectArray(e,t):n(e)?this.deserializeObject(e,t):void this.error("Fail to deserialize: value is not an Array nor an Object.\nReceived: "+JSON.stringify(e)+".")},p.prototype.deserializeObject=function(e,t){var i=this;if(null===e)return"disallow"===this.options.nullishPolicy.null&&this.error("Fail to deserialize: null is not assignable to type Object."),null;if(void 0!==e){if(r(e)&&(e=u(e)),n(e)){var o=new t({}),a=this.getJsonPropertiesMetadata(o);return a?(Object.keys(a).forEach((function(t){var r=a[t],n=i.deserializeProperty(o,t,e,r);if(r.required&&s(n)){var l=o.constructor.name;i.error("Property '"+t+"' is required in "+l+" "+JSON.stringify(e)+".")}i.isAllowedProperty(n)&&(o[t]=n)})),o):o}this.error("Fail to deserialize: type '"+typeof e+"' is not assignable to type 'Object'.\nReceived: "+JSON.stringify(e))}else"disallow"===this.options.nullishPolicy.undefined&&this.error("Fail to deserialize: undefined is not assignable to type Object.")},p.prototype.deserializeObjectArray=function(e,t){var i=this;if(null===e)return"disallow"===this.options.nullishPolicy.null&&this.error("Fail to deserialize: null is not assignable to type Array."),null;if(void 0!==e){if(r(e)&&(e=u(e)),o(e))return e.map((function(e){return i.deserializeObject(e,t)}));this.error("Fail to deserialize: type '"+typeof e+"' is not assignable to type 'Array'.\nReceived: "+JSON.stringify(e))}else"disallow"===this.options.nullishPolicy.undefined&&this.error("Fail to deserialize: undefined is not assignable to type Array.")},p.prototype.serialize=function(e){return o(e)?this.serializeObjectArray(e):n(e)?this.serializeObject(e):void this.error("Fail to serialize: value is not an Array nor an Object.\nReceived: "+JSON.stringify(e)+".")},p.prototype.serializeObject=function(e){var t=this;if(null===e)return"disallow"===this.options.nullishPolicy.null&&this.error("Fail to serialize: null is not assignable to type Object."),null;if(void 0!==e){if(!n(e))return e;var i=this.getJsonPropertiesMetadata(e);if(!i)return e;var r={},a=Object.keys(e);return Object.keys(i).forEach((function(n){if(a.includes(n)){var s=i[n],l=void 0;s.beforeSerialize&&(l=e[n],e[n]=s.beforeSerialize(e[n],e));var u=t.serializeProperty(e,n,s);if(s.afterSerialize&&(u=s.afterSerialize(u,e)),e[n]=l||e[n],o(s.name))s.name.forEach((function(e){t.isAllowedProperty(u[e])&&(r[e]=u[e])}));else if(t.isAllowedProperty(u))if(s.isNameOverridden||void 0===t.options.formatPropertyName)r[s.name]=u;else{var c=t.options.formatPropertyName(s.name);r[c]=u}}})),r}"disallow"===this.options.nullishPolicy.undefined&&this.error("Fail to serialize: undefined is not assignable to type Object.")},p.prototype.serializeObjectArray=function(e){var t=this;if(null===e)return"disallow"===this.options.nullishPolicy.null&&this.error("Fail to serialize: null is not assignable to type Array."),null;if(void 0!==e){if(o(e))return e.map((function(e){return t.serializeObject(e)}));this.error("Fail to serialize: type '"+typeof e+"' is not assignable to type 'Array'.\nReceived: "+JSON.stringify(e)+".")}else"disallow"===this.options.nullishPolicy.undefined&&this.error("Fail to serialize: undefined is not assignable to type Array.")},p.prototype.deserializeProperty=function(e,t,r,n){var o;if(!s(r)){var a=this.getDataSource(r,n,this.options.formatPropertyName);if(s(a))return a;var u,c=i.getType(e,t),p="array"===(null===(o=null==c?void 0:c.name)||void 0===o?void 0:o.toLowerCase()),f=n.type||c;n.beforeDeserialize&&(a=n.beforeDeserialize(a,e));var d=n.predicate;return n.isDictionary?u=this.deserializeDictionary(a,f,d):p?u=this.deserializeArray(a,f,d):!l(f)&&!d||d&&!d(a,r)?u=this.deserializePrimitive(a,f.name):(f=n.predicate?n.predicate(a,r):f,u=this.deserializeObject(a,f)),n.afterDeserialize&&(u=n.afterDeserialize(u,e)),u}},p.prototype.deserializePrimitive=function(e,t){if(s(t))return e;if(typeof e===(t=t.toLowerCase()))return e;var i="Fail to deserialize: type '"+typeof e+"' is not assignable to type '"+t+"'.\nReceived: "+JSON.stringify(e);switch(t){case"string":var r=e.toString();return"[object Object]"===r?void this.error(i):r;case"number":return function(e){return"number"==typeof e}(e)?+e:void this.error(i);case"boolean":return void this.error(i);case"date":return function(e){return!a(e)&&!o(e)&&!isNaN(Date.parse(e))}(e)?new Date(e):void this.error(i);default:return e}},p.prototype.deserializeDictionary=function(e,t,i){var r=this;if(n(e)){var o={};return Object.keys(e).forEach((function(n){var a=i?i(e[n],e):void 0;l(t)||a?o[n]=r.deserializeObject(e[n],a||t):o[n]=r.deserializePrimitive(e[n],typeof e[n])})),o}this.error("Fail to deserialize: type '"+typeof e+"' is not assignable to type 'Dictionary'.\nReceived: "+JSON.stringify(e)+".")},p.prototype.deserializeArray=function(e,t,i){var r=this;if(o(e))return e.map((function(n){return l(t)||i?(t=i?i(n,e):t,r.deserializeObject(n,t)):r.deserializePrimitive(n,typeof n)}));this.error("Fail to deserialize: type '"+typeof e+"' is not assignable to type 'Array'.\nReceived: "+JSON.stringify(e))},p.prototype.error=function(e){this.options.errorCallback&&this.options.errorCallback(e)},p.prototype.getClassesJsonPropertiesMetadata=function(e,t){return e?e.reduce((function(e,r){var n=i.getJsonPropertiesMetadata(t,r);return n&&e.push(n),e}),[]):[]},p.prototype.getDataSource=function(e,t,i){var r=t.name,n=t.isNameOverridden;if(o(r)){var a={};return r.forEach((function(t){return a[t]=e[t]})),a}return!n&&i?(r=i(r),e[r]):e[r]},p.prototype.getJsonPropertiesMetadata=function(t){var r,n=(null!==(r=i.getJsonObjectMetadata(t.constructor))&&void 0!==r?r:{}).baseClassNames,o=i.getJsonPropertiesMetadata(t);if(!(o||n&&n.length))return o;if(n&&n.length){var a=this.getClassesJsonPropertiesMetadata(n,t);return this.mergeJsonPropertiesMetadata.apply(this,e(e([],a),[o]))}return o},p.prototype.isAllowedProperty=function(e){if(s(e)){if("disallow"===this.options.nullishPolicy[""+e])return this.error("Disallowed "+e+" value detected."),!1;if("remove"===this.options.nullishPolicy[""+e])return!1}return!0},p.prototype.mergeJsonPropertiesMetadata=function(){for(var e=[],i=0;i<arguments.length;i++)e[i]=arguments[i];var r={};return e.forEach((function(e){e&&Object.keys(e).forEach((function(i){r[i]=t(t({},r[i]),e[i])}))})),r},p.prototype.serializeDictionary=function(e){var t=this;if(n(e)){var i={};return Object.keys(e).forEach((function(r){i[r]=t.serializeObject(e[r])})),i}this.error("Fail to serialize: type '"+typeof e+"' is not assignable to type 'Dictionary'.\nReceived: "+JSON.stringify(e)+".")},p.prototype.serializeProperty=function(e,t,r){var n,o,s=e[t],u=i.getType(e,t),c="array"===(null===(n=null==u?void 0:u.name)||void 0===n?void 0:n.toLocaleLowerCase()),p=r.predicate,f=r.type||u,d=l(f);return s&&(d||p)?c?this.serializeObjectArray(s):r.isDictionary?this.serializeDictionary(s):this.serializeObject(s):"date"===(null===(o=null==f?void 0:f.name)||void 0===o?void 0:o.toLocaleLowerCase())&&a(s)?s.toISOString():s},p}(),y=function(t){var r=i.getBaseClass(t);return r&&r.name?e(e([],y(r)),[r.name]):[]},v=function(){return function(e){var t=y(e);i.setJsonObject({baseClassNames:t},e)}},h=function(e){return function(t,r,n){var o;if(void 0===r&&t.prototype){var a=i.getParamTypes(t)[n];r=g(t.prototype.constructor).get(n),t=t.prototype,i.setType(a,t,r)}var s=null!==(o=i.getJsonPropertiesMetadata(t))&&void 0!==o?o:{};s[r]=b(r,e),i.setJsonPropertiesMetadata(s,t)}},g=function(e){var t,i=e.toString().split("}")[0].replace(/(\/\*[\s\S]*?\*\/|\/\/.*$)/gm,"").replace(/[\r\t\n\v\f ]/g,""),r=i.length;","===i[r-2]&&(t=i[r-1]);var n=t?new RegExp("(?:(this|"+t+"|\\("+t+"=t.call\\(this(,.)*\\)\\))\\.)([^,;\n}]+)","gm"):new RegExp("(?:(this)\\.)([^,;\n}]+)","gm"),o=new Map,a=/(?:.*(?:constructor|function).*?(?=\())(?:\()(.+?(?=\)))/m.exec(i);if(!a||!a.length)return o;for(var s,l=a[1].split(","),u=function(){var e=s.length-1,t=s[e].split("="),i=l.findIndex((function(e){return e===t[1]}));i>-1&&o.set(i,t[0])};s=n.exec(i);)u();return o},b=function(e,o){var a={name:e.toString()};return o?r(o)?(a.name=o,a.isNameOverridden=!0,a):(n(o)&&(a=t(t({},a),o),o.name&&(a.name=o.name,a.isNameOverridden=!0),function(e){if(!e)return!1;var t=i.getParamTypes(e),r=e.length;return(1===r||2===r)&&!t}(o.type)&&(delete a.type,a.predicate=o.type)),a):a};export{v as JsonObject,h as JsonProperty,d as JsonSerializer,c as JsonSerializerOptions,f as logError,p as throwError};
{
"name": "typescript-json-serializer",
"version": "3.4.5",
"version": "4.0.0",
"description": "Typescript library to serialize classes into json and deserialize json into classes.",

@@ -11,10 +11,8 @@ "source": "src/index.ts",

"build": "rollup -c",
"cover": "jest --coverage",
"cover": "rimraf coverage && jest --coverage",
"lint": "eslint . --ext .ts --fix",
"lint:ci": "eslint . --ext .ts",
"postbuild": "npm run types",
"prebuild": "rimraf dist",
"test": "jest",
"test:ci": "jest --reporters=default --reporters=jest-junit --coverage --coverageReporters=lcov --coverageReporters=text-lcov",
"types": "tsc src/index.ts -d --emitDeclarationOnly --declarationDir dist"
"test:ci": "jest --coverage"
},

@@ -21,0 +19,0 @@ "repository": {

@@ -5,3 +5,3 @@ # typescript-json-serializer

![npm](https://img.shields.io/npm/dt/typescript-json-serializer)
![npm bundle size (version)](https://img.shields.io/bundlephobia/minzip/typescript-json-serializer/3.4.4)
![npm bundle size (version)](https://img.shields.io/bundlephobia/minzip/typescript-json-serializer/4.0.0)
[![Coverage Status](https://coveralls.io/repos/github/GillianPerard/typescript-json-serializer/badge.svg)](https://coveralls.io/github/GillianPerard/typescript-json-serializer)

@@ -12,2 +12,10 @@ [![Known Vulnerabilities](https://snyk.io/test/github/gillianperard/typescript-json-serializer/badge.svg?targetFile=package.json)](https://snyk.io/test/github/gillianperard/typescript-json-serializer?targetFile=package.json)

## Summary
1. [Installation](#installation)
2. [Usage](#usage)
3. [API](#api)
4. [Development](#development)
5. [Thanks to](#thanks-to)
## Installation

@@ -36,131 +44,42 @@

**WARNING:** If you use CRA (create-react-app) please refer to the [Using with Create React App](#using-with-create-react-app) section.
## Usage
## Import
There are two decorators and two functions that you can import inside a typescript file.
```typescript
import {
JsonProperty,
Serializable,
deserialize,
serialize
} from 'typescript-json-serializer';
```
import { JsonSerializer, throwError } from 'typescript-json-serializer';
## Library
import { json } from '../json/data';
import { Organization } from '../models/organization';
### Decorators
// Instantiate a default serializer
const defaultSerializer = new JsonSerializer();
```typescript
// Serializable decorator set a class as serializable.
// It can take options as parameter:
// - formatPropertyNames function to format the property names
// provided by the json you want to serialize to match
// with your class property names
// Or you can instantiate a serializer with your custom options
const customSerializer = new JsonSerializer({
// Throw errors instead of logging
errorCallback: throwError,
type FormatPropertyNameProto = (propertyName: string) => string;
type SerializableOptions = {
formatPropertyNames: FormatPropertyNameProto
}
// Allow all nullish values
nullishPolicy: {
undefined: 'allow',
null: 'allow'
};
@Serializable(options?: SerializableOptions)
```
// e.g. if all the properties in the json object are prefixed by '_'
formatPropertyName: (propertyName: string) => `_${propertyName}`;
})
```typescript
// JsonProperty decorator set metadata to the property.
// It can take some optional parameters like:
// - the name of json property if diverge from the class property
// (this value override the `formatPropertyNames` option from
// `Serializable` decorator)
// - the type of the property (if needed)
// - a predicate function that return a type (if needed)
// - a function to transform data before serialize
// - a function to transform data after serialize
// - a function to transform data before deserialize
// - a function to transform data after deserialize
// - the names of properties to merge (the `formatPropertyNames`
// from `Serializable` decorator is ignored)
// - a boolean to tell that the property is a dictionary
// - a boolean to tell that the property is required
// (throw an error if undefined, null or missing)
// Deserialize
const organization = defaultSerializer.deserialize(json, Organization);
// BREAKING CHANGES: since version 3.0.0
// - onSerialize has become afterSerialize
// - onDeserialize has become beforeDeserialize
// - postDeserialize has become afterDeserialize
type IOProto = (property: any, currentInstance?: any) => {};
type PredicateProto = (property: any, parentProperty?: any) => {};
@JsonProperty(args?:
| string
| {
name?: string,
type?: Function,
beforeSerialize?: IOProto,
afterSerialize?: IOProto,
beforeDeserialize?: IOProto,
afterDeserialize?: IOProto,
isDictionary?: boolean,
required?: boolean
}
| {
name?: string,
predicate?: PredicateProto,
beforeSerialize?: IOProto,
afterSerialize?: IOProto,
beforeDeserialize?: IOProto,
afterDeserialize?: IOProto,
isDictionary?: boolean,
required?: boolean
}
| {
names?: Array<string>,
type?: Function,
beforeSerialize?: IOProto,
afterSerialize?: IOProto,
beforeDeserialize?: IOProto,
afterDeserialize?: IOProto,
required?: boolean
}
| {
names?: Array<string>,
predicate?: PredicateProto,
beforeSerialize?: IOProto,
afterSerialize?: IOProto,
beforeDeserialize?: IOProto,
afterDeserialize?: IOProto,
required?: boolean
})
// Serialize
const data = defaultSerializer.serialize(organization);
```
### Functions
### Examples
```typescript
// serialize function transform typescript class into json.
// It takes two parameters:
// - a instance of the class to serialize
// - a boolean to remove undefined property (default true)
#### Classes
serialize(instance: any, removeUndefined: boolean = true): any
```
```typescript
// deserialize function transform json into typescript class.
// It takes two parameters:
// - json data
// - the class you want to deserialize into
deserialize<T>(json: any, type: new (...params) => T): T
```
## Example
### Classes
```typescript
// Import decorators from library
import { Serializable, JsonProperty } from 'typescript-json-serializer';
import { JsonObject, JsonProperty } from 'typescript-json-serializer';

@@ -181,6 +100,6 @@ // Enums

// Create a serializable class: LivingBeing
// Create a JsonObject class: LivingBeing
// Serializable decorator
@Serializable()
// JsonObject decorator
@JsonObject()
export class LivingBeing {

@@ -193,5 +112,5 @@

// Create a serializable class that extends LivingBeing: Human
// Create a JsonObject class that extends LivingBeing: Human
@Serializable()
@JsonObject()
export class Human extends LivingBeing {

@@ -215,5 +134,5 @@ constructor(

// Create a serializable class: PhoneNumber
// Create a JsonObject class: PhoneNumber
@Serializable()
@JsonObject()
export class PhoneNumber {

@@ -225,5 +144,5 @@ @JsonProperty() countryCode: string;

// Create a serializable class that extends Human: Employee
// Create a JsonObject class that extends Human: Employee
@Serializable()
@JsonObject()
export class Employee extends Human {

@@ -236,3 +155,3 @@ /** The employee's email */

@JsonProperty({
predicate: property => {
type: property => {
if (property && property.value !== undefined) {

@@ -258,5 +177,5 @@ return PhoneNumber;

// Create a serializable class: Animal
// Create a JsonObject class: Animal
@Serializable()
@JsonObject()
export class Animal {

@@ -284,5 +203,5 @@

// Create a serializable class that extends Animal (which extends LivingBeing): Panther
// Create a JsonObject class that extends Animal (which extends LivingBeing): Panther
@Serializable()
@JsonObject()
export class Panther extends Animal {

@@ -304,6 +223,6 @@

// Create a serializable class that extends Animal
// Create a JsonObject class that extends Animal
// (which extends LivingBeing): Snake
@Serializable()
@JsonObject()
export class Snake extends Animal {

@@ -321,6 +240,6 @@

// Create a serializable empty class that extends Animal
// Create a JsonObject empty class that extends Animal
// (which extends LivingBeing): UnknownAnimal
@Serializable()
@JsonObject()
export class UnknownAnimal extends Animal {

@@ -333,3 +252,3 @@ public constructor(name: string) {

// Create a serializable class: Zoo
// Create a JsonObject class: Zoo

@@ -366,3 +285,3 @@ // Function to transform coordinates into an array

@Serializable()
@JsonObject()
export class Zoo {

@@ -396,3 +315,3 @@

// object into the correct child class
@JsonProperty({ name: 'Animals', predicate: snakeOrPanther })
@JsonProperty({ name: 'Animals', type: snakeOrPanther })
animals: Array<Animal>;

@@ -402,3 +321,3 @@

// Use again the predicate function
@JsonProperty({ predicate: snakeOrPanther })
@JsonProperty({ type: snakeOrPanther })
mascot: Panther | Snake;

@@ -413,3 +332,3 @@

isDictionary: true,
predicate: property => {
type: property => {
if (property && property.value !== undefined) {

@@ -427,18 +346,10 @@ return PhoneNumber;

public constructor() { }
}
// Create a serializable class that extends Society: Organization
// Create a JsonObject class that extends Society: Organization
const prefixWithUnderscore = (propertyName: string) => `_${propertyName}`
// Instead of defining the JsonProperty name for each property
// just use a function to do it for all of them.
// Warning: The properties of the base class will be formatted as well
@Serializable({ formatPropertyNames: prefixWithUnderscore })
@JsonObject()
export class Organization extends Society {
// Override `formatPropertyNames`
@JsonProperty({ name: 'zoos', type: Zoo }) zoos: Array<Zoo>;
@JsonProperty({ type: Zoo }) zoos: Array<Zoo>;
@JsonProperty({ isDictionary: true })

@@ -454,6 +365,6 @@ zoosName: { [id: string]: string };

@JsonProperty({
names: [
'_mainShareholder',
'_secondaryShareholder',
'_thirdShareholder'
name: [
'mainShareholder',
'secondaryShareholder',
'thirdShareholder'
],

@@ -464,5 +375,5 @@ type: Human,

return {
_mainShareholder: value[0],
_secondaryShareholder: value[1],
_thirdShareholder: value[2]
mainShareholder: value[0],
secondaryShareholder: value[1],
thirdShareholder: value[2]
};

@@ -475,5 +386,5 @@ }

// Create a serializable class: Society
// Create a JsonObject class: Society
@Serializable()
@JsonObject()
export class Organization {

@@ -485,3 +396,3 @@ @JsonProperty() id: string;

### Json data
#### Json data

@@ -491,5 +402,5 @@ ```typescript

export const data: any = {
_id: '1',
_name: 'Zoos Organization',
_zoosName: {
id: '1',
name: 'Zoos Organization',
zoosName: {
'15': 'The Greatest Zoo',

@@ -635,3 +546,3 @@ '16': 'Zoo Zoo'

],
_mainShareholder: {
mainShareholder: {
humanId: 100,

@@ -642,103 +553,341 @@ name: 'Elon Musk',

},
_secondaryShareholder: null
secondaryShareholder: null
};
```
### Serialize & Deserialize
## API
```typescript
// Import functions from library
import { deserialize, serialize } from 'typescript-json-serializer';
### Decorators
import { json } from '../json/data';
import { Organization } from '../models/organization';
**@JsonObject()**
Used to make a class serializable.
// deserialize
const organization = deserialize<Organization>(json, Organization);
##### **Example**
// serialize
const data = serialize(organization);
// or
const data = serialize(organization, false);
```typescript
@JsonObject()
class MyClass {}
```
## Using with Create React App
**@JsonProperty()**
Used to make a class property serializable, property will be ignored if not set.
If you are using [CRA](https://create-react-app.dev/) to create your React App you will need to add a custom configuration in order to add `Decorator` and `Metadata` features (not supported by React) using [customize-cra](https://github.com/arackaf/customize-cra) and [react-app-rewired](https://github.com/timarney/react-app-rewired/).
##### **Parameters**
First, don't forget to add `emitDecoratorMetadata` and `experimentalDecorators` inside the `tsconfig.json` file (explain in the [Installation](#installation) section).
**options**
Type: `string` | [`JsonPropertyOptions`](#jsonpropertyoptions)
Optional: `true`
Description: The option to customize the serialization/deserialization of the target property.
Next install the dependencies to override the React build config:
##### **Example**
```sh
npm install -D customize-cra react-app-rewired
# or
yarn add -D customize-cra react-app-rewired
```typescript
@JsonProperty(options) myProperty: string;
```
Replace the scripts using `react-scripts` in the `package.json` file by `react-app-rewired`:
### JsonSerializer
```json
// example
#### Constructor
```typescript
constructor(options?: Partial<JsonSerializerOptions>) {}
```
##### **Parameters**
**options**
Type: <code>Partial<[JsonSerializerOptions](#jsonserializeroptions)></code>
Optional: `true`
Description: The options to customize the serializer.
#### Properties
**options**
Type: <code>Partial<[JsonSerializerOptions](#jsonserializeroptions)></code>
Optional: `false`
Description: The options to customize the serializer.
Default value:
```typescript
{
...
"scripts": {
...
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-app-rewired eject"
...
},
...
errorCallback: logError,
nullishPolicy: {
undefined: 'remove',
null: 'allow'
}
}
```
Install dependencies to add support for `Decorator` and `Metadata`:
#### Methods
**deserialize()**
To use when you don't know if the value to deserialize is an object or an array.
```typescript
deserialize<T extends object>(
value: string | object | Array<object>,
type: Type<T>
): T | Array<T|Nullish> | Nullish
```
##### **Parameters**
**value**
Type: `string` | `object` | `Array<object>`
Optional: `false`
Description: The value to deserialize.
**type**
Type: [`Type<T>`](#typet)
Optional: `false`
Description: The constructor class to deserialize into.
##### **Return**
`T` or <code>Array<T|[Nullish](#nullish)></code> or [`Nullish`](#nullish)
---
**deserializeObject()**
To use when the value to deserialize is an object.
```typescript
deserializeObject<T extends object>(
obj: string | object,
type: Type<T>
): T | Nullish
```
##### **Parameters**
**obj**
Type: `string` | `object`
Optional: `false`
Description: The object to deserialize.
**type**
Type: [`Type<T>`](#typet)
Optional: `false`
Description: The constructor class to deserialize into.
##### **Return**
`T` or [`Nullish`](#nullish)
---
**deserializeObjectArray()**
To use when the value to deserialize is an array.
```typescript
deserializeObjectArray<T extends object>(
array: string | Array<any>,
type: Type<T>
): Array<T|Nullish> | Nullish
```
##### **Parameters**
**array**
Type: `string` | `Array<any>`
Optional: `false`
Description: The object to deserialize.
**type**
Type: [`Type<T>`](#typet)
Optional: `false`
Description: The constructor class to deserialize into.
##### **Return**
<code>Array<T|[Nullish](#nullish)></code> or [`Nullish`](#nullish)
---
**serialize()**
To use when you don't know if the value to serialize is an object or an array
```typescript
serialize(value: object | Array<object>): object | Array<object|Nullish> | Nullish
```
##### **Parameters**
**value**
Type: `object` | `Array<object>`
Optional: `false`
Description: The object or the array of objects to serialize.
##### **Return**
`object` or <code>Array<object|[Nullish](#nullish)></code> or [`Nullish`](#nullish)
---
**serializeObject()**
To use when the value to serialize is an object.
```typescript
serializeObject(instance: object): object | Nullish
```
##### **Parameters**
**instance**
Type: `object`
Optional: `false`
Description: The object to serialize.
##### **Return**
`object` or [`Nullish`](#nullish)
---
**serializeObjectArray()**
To use when the value to serialize is an array of objects.
```typescript
serializeObjectArray(array: Array<object>): Array<object|Nullish> | Nullish
```
##### **Parameters**
**array**
Type: `Array<object>`
Optional: `false`
Description: The array of objects to serialize.
##### **Return**
<code>Array<object|[Nullish](#nullish)></code> or [`Nullish`](#nullish)
### Definitions
#### **Types**
##### **JsonPropertyOptions**
```typescript
name?: string | Array<string>;
type?: Function | PredicateProto;
isDictionary?: boolean;
required?: boolean;
beforeSerialize?: IOProto;
afterSerialize?: IOProto;
beforeDeserialize?: IOProto;
afterDeserialize?: IOProto;
```
##### **JsonSerializerOptions**
```typescript
errorCallback?: ErrorCallback = logError;
nullishPolicy: NullishPolicy = {
undefined: 'remove',
null: 'allow'
};
formatPropertyName?: FormatPropertyNameProto;
```
##### **NullishPolicy**
```typescript
undefined: Policy;
null: Policy;
```
#### **Value types**
##### **Nullish**
```typescript
null | undefined
```
##### **Policy**
```typescript
'allow' | 'disallow' | 'remove'
```
#### **Functions types**
##### **ErrorCallback**
```typescript
(message: string) => void
```
The library provide two built-in methods:
- `logError` that logs the error.
- `throwError` that throws the error.
##### **FormatPropertyNameProto**
```typescript
(propertyName: string) => string;
```
##### **IOProto**
```typescript
(property: any, currentInstance?: any) => any
```
##### **PredicateProto**
```typescript
(property: any, parentProperty?: any) => any
```
##### **Type\<T>**
```typescript
new (...args: Array<any>) => T;
```
Note: represent a `constructor`.
## Development
### Prerequisites
- NodeJS: [https://nodejs.org](https://nodejs.org/en/)
- Yarn: [https://yarnpkg.com](https://yarnpkg.com/)
### Install dependencies
```sh
npm install -D @babel/plugin-proposal-decorators \
@babel/preset-typescript \
babel-plugin-parameter-decorator \
babel-plugin-transform-typescript-metadata
# or
yarn add -D @babel/plugin-proposal-decorators \
@babel/preset-typescript \
babel-plugin-parameter-decorator \
babel-plugin-transform-typescript-metadata
yarn
```
Create the `config-overrides.js` file in the root of your project
with the following content:
### Run build
```js
const {
override,
addDecoratorsLegacy,
addBabelPlugin,
addBabelPreset,
} = require("customize-cra");
```sh
yarn build
```
module.exports = override(
addDecoratorsLegacy(),
addBabelPlugin("babel-plugin-parameter-decorator"),
addBabelPlugin("babel-plugin-transform-typescript-metadata"),
addBabelPreset(["@babel/preset-typescript"])
);
### Run linter
```sh
yarn lint
```
## Test
### Run tests
```sh
npm run test
# or
yarn test
```
## Author
## Thanks to
### Author
Gillian Pérard - [@GillianPerard](https://github.com/GillianPerard)
## Contributors
### Contributors
* Hyeonsoo David Lee - [@civilizeddev](https://github.com/civilizeddev)
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc