{"id":19185914,"url":"https://github.com/acacode/serializy","last_synced_at":"2025-05-08T01:17:04.532Z","repository":{"id":108458643,"uuid":"190085098","full_name":"acacode/serializy","owner":"acacode","description":"❤️ Isolate server side models at frontend side ❤️","archived":false,"fork":false,"pushed_at":"2020-07-17T16:49:21.000Z","size":1073,"stargazers_count":4,"open_issues_count":3,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-08T01:16:58.159Z","etag":null,"topics":["convert","data","json","jsonschema","mapper","object","schema","serialization","serializer","validation","validator"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/acacode.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null},"funding":{"ko_fi":"acacode"}},"created_at":"2019-06-03T21:30:36.000Z","updated_at":"2025-02-01T05:12:21.000Z","dependencies_parsed_at":"2023-05-09T20:46:06.738Z","dependency_job_id":null,"html_url":"https://github.com/acacode/serializy","commit_stats":{"total_commits":139,"total_committers":3,"mean_commits":"46.333333333333336","dds":0.3237410071942446,"last_synced_commit":"9656f72da4d378665eb40b118a9a53511f0250e7"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/acacode%2Fserializy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/acacode%2Fserializy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/acacode%2Fserializy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/acacode%2Fserializy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/acacode","download_url":"https://codeload.github.com/acacode/serializy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252978811,"owners_count":21834920,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["convert","data","json","jsonschema","mapper","object","schema","serialization","serializer","validation","validator"],"created_at":"2024-11-09T11:12:29.383Z","updated_at":"2025-05-08T01:17:04.447Z","avatar_url":"https://github.com/acacode.png","language":"TypeScript","funding_links":["https://ko-fi.com/acacode"],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n  [![serializy](./assets/logo.png)](https://www.npmjs.com/package/serializy) \n\n  [![license](https://img.shields.io/badge/license-MIT-red.svg)](./LICENSE)\n  [![npm](https://img.shields.io/npm/v/serializy.svg)](https://www.npmjs.com/package/serializy)\n  [![](https://data.jsdelivr.com/v1/package/npm/serializy/badge)](https://www.jsdelivr.com/package/npm/serializy)\n  [![build status](https://img.shields.io/travis/acacode/serializy.svg)](https://travis-ci.org/acacode/serializy)\n  [![downloads per month](https://img.shields.io/npm/dm/serializy.svg)](http://npm-stat.com/charts.html?package=serializy)\n  [![min size](https://badgen.net/bundlephobia/min/serializy)](https://bundlephobia.com/result?p=serializy)\n  [![minzip size](https://badgen.net/bundlephobia/minzip/serializy)](https://bundlephobia.com/result?p=serializy)\n  [![install size](https://packagephobia.now.sh/badge?p=serializy)](https://packagephobia.now.sh/result?p=serializy)\n\n  \u003cp\u003e\n    Object schema validation and data serialization\n  \u003c/p\u003e\n\u003c/div\u003e\n\n## ❓ What is that ?\n\nThis thing allows you to don't have to worry about changing server-side structures!  \n  \nSometimes when server change JSON structures or frontend start using different API  \nThese situations can make some problems in frontend applications  \nBecause mostly use the same structure from server when develop user interfaces  \n  \nBut with **serializy** you can describe structure which you will use and which server wants to see  \n\nSounds interesting, yeah ? :-)  \nScroll down and take a look at the examples ;-)\n\n\n## 💡 How to use\n\nNothing to hard, just create a class or simple object which will contain all your structure declarations (using `field()`, `fieldArray()`).  \nAnd send this class/object to the `model()` function as argument  \nLike in example:  \n\n```js\nimport { field, fieldArray, model } from 'serializy'\n\nclass DeveloperDeclaration {\n  likeCoffee = field('LIKE_COFFEE', 'boolean')\n  languages = fieldArray('LaNgUagEs', 'string')\n}\n```\nCreating declaration using class is not necessarily, you can create just a simple object:  \n```js\n\nconst DeveloperDeclaration = {\n  likeCoffee: field('LIKE_COFFEE', 'boolean'),\n  languages: fieldArray('LaNgUagEs', 'string'),\n}\n\n```\n  \n```js\nconst DeveloperModel = model(DeveloperDeclaration)\n```\n\nAnd when you get server structure just create instance of your declared model:  \n\n```js\n\nconst ServerStructure = {\n  LIKE_COFFEE: true,\n  LaNgUagEs: ['GoLang', 'Python']\n}\n\nconst developer = new DeveloperModel(ServerStructure)\n/*\n  developer object will be\n  {\n    likeCoffee: true,\n    languages: ['GoLang', 'Python']\n  }\n*/\n\n```\n\nBut what if you need to change your client model and send it to the server ?  \nYou can use `.deserialize()` of the each created instance of declared model:  \n\n```js\n\ndeveloper.likeCoffee = false\ndeveloper.languages.push('JavaScript')\n\ndeveloper.deserialize()\n/*\n{\n  LIKE_COFFEE: false,\n  LaNgUagEs: ['GoLang', 'Python', 'JavaScript']\n}\n*/\n```\nAlso your created structure declaration (like `DeveloperModel`) have methods:  \n- **`.serialize(serverModel)`** - to convert server-side structure to client-side  \n- **`.deserialize(clientModel)`** - to convert client-side structure to server-side  \nIn addition, structure declarations have methods:  \n- **`.getUsagePropertyNames()`** - returns array of usage property names declared in model  \n- **`.getOriginalPropertyNames()`** - returns array of original property names declared in model  \n- **`.getPropertiesMap(reverseNames?: boolean)`** - returns map where key is usage property name and value is original property name. `reverseNames` - just changing sides key/value  \n\n## 📚 Documentation  \n\nSerializy have exports: `field()`, `fieldArray()`, `model()`  \n\n\u003chr\u003e\n\n### 🔹 **`field(...options: FieldOptions)`**[[Source]](./src/field_declaration.ts#L102)  \n\nThis function needed for transforming property of the original structure to usage property.  \nSyntax: `field(...options: FieldOptions)` or `field(...options: FieldOptions)(propertyOptions: Partial\u003cCommonPropertyOptions\u003e)`  \n\nProperty options it is configuration object which can allows to change various behaviour of this property. Currently object have:  \n```js\n{\n  optional: boolean\n  // true - will say to serializy that this property\n  // can be not contains in original/usage structure\n  // By default: false\n}\n```\n\nFor example, you've got object `{ FirsT_naMe: 'John' }` and you need to convert property `\"FirsT_naMe\"` to the `\"firstName\"`, you can just write:  \n```js\n  const Struct = model({ // it is required wrapper for structure declarations\n    firstName: field('FirsT_naMe', 'string')\n    // firstName - name of the usage property\n    // 'FirsT_naMe' (first arg) - name of the original property\n    // 'string' (second arg) - type of the both sides properties\n  })\n```\nOr you've got object with string value of number like `{ Age: '19' }` but you need to use type number, you can just write:  \n```js\n  const Struct = model({ // it is required wrapper for structure declarations\n    age: field('Age', 'string', 'number')\n    // firstName - name of the usage property\n    // 'FirsT_naMe' (first arg) - name of the original property\n    // 'string' (second arg) - type of original property\n    // 'number' (third arg) - type of usage property\n  })\n```\n\nOptions:  \n\n- **`field(originalPropertyName: string, originalType?: string, usageType?: string)`**\n  \n  This type of the field declaration allows you to describe simple properties which are mostly primitive values.  \n  Arguments:  \n      - **`originalPropertyName: string`** - name of the property in original structure.  Original property with this name will be assigned to usage property.  \n      - **`originalType?: string`** - type of the original property.    \n      - **`usageType?: string`** - needed type of the usage property.  \n\n    note: `originalType` and `usageType` should be one of the [following strings](./src/converter.ts#L30) (`'boolean'`, `'number'`, `'string'`, `'object'`, `'any'`)  \n\n  Examples:  \n  ```js\n\n  const Model = model({\n    someProp: field('SomeProp','number','string')\n    hidden: field('Hidden','boolean')({ optional: true })\n    any: field('Any', 'any')\n  })\n\n  const structure = new Model({\n    SomeProp: 12345,\n    Any: { foo: 'bar' }\n  })\n\n  console.log(structure.someProp) // '12345'\n  console.log(structure.deserialize()) // { SomeProp: 12345, Any: { foo: 'bar' } }\n  ```  \n![image](./assets/empty_block.png)  \n\n\n\n  \n  \n  \n- **`field(originalPropertyName: string, modelDeclaration: ModelDeclaration)`**  \n\n  This type of the field declaration allows you to describe complex structures to usage structures    \n  Arguments:  \n      - **`originalPropertyName: string`** - name of the property in original structure.  Original property with this name will be assigned to usage property.  \n      - **`modelDeclaration: ModelDeclaration`** - model declaration needed for convert original object into usage object.  \n          [`modelDeclaration`](./src/field_declaration.ts#L8) should be `object`/`model(DeclarationsClass)`  \n          And keys/properties should have values created via `field()`, `fieldArray()` function  \n\n\n  Examples:  \n  ```js\n  const FooModel = model(class FooModel {\n    foo = field('Foo', 'number', 'string')\n  })\n\n  class Model = model({class Model {\n    fooStruct = field('FooStruct', FooModel)\n  }})\n  ```  \n  ```js\n  class Model = model({class Model {\n    // or you can not create additional wrapped model() class\n    fooStruct = field('FooStruct', {\n      foo = field('Foo', 'number', 'string')\n    })\n  }})\n\n  const fooBarStruct = new Model({\n    FooStruct: { Foo: 12345 }\n  })\n\n  console.log(fooBarStruct) // { fooStruct: { foo: '12345' } }\n  console.log(fooBarStruct.deserialize()) // { FooStruct: { Foo: 12345 } }\n  ```  \n![image](./assets/empty_block.png)  \n\n\n  \n  \n\n  \n- **`field(customSerializer: function, customDeserializer?: function)`**  \n\n  You can attach custom serializer/deserializer for specific cases.  \n  Arguments:  \n      - **`customSerializer: function`** - this function should return value of the usage property. Takes one argument - original structure   \n      - **`customDeserializer?: function`** - this function should return object which will been merged to the original structure. Takes one argument - usage structure  \n\n\n  Examples:  \n  ```js\n  const Model = model({\n    barBaz: field(\n      ({ bar, baz }) =\u003e `${bar}/${baz}`,\n      ({ barBaz }) =\u003e {\n        const [bar, baz] = barBaz.split('/')\n        return { bar, baz }\n      }\n    ),\n    foo: field(({ foo }) =\u003e foo, ({ foo }) =\u003e ({ foo })) // in this case just better to use field('foo')\n  })\n\n  const structure = new Model({\n    foo: 'foo',\n    bar: 'bar',\n    baz: 'baz'\n  })\n\n  console.log(structure) // { barBaz: 'bar/baz', foo: 'foo' }\n  console.log(structure.deserialize()) // { foo: 'foo', bar: 'bar', baz: 'baz' }\n  ```  \n![image](./assets/empty_block.png)  \n\n\n  \n  \n\n  \n- **`field({ name: 'property_name', type: 'original_type', usageType: 'usage_type' }: object)`**  \n\n  This is just another way to describe property.   \n  Properties:  \n      - **`name: string`** - key name in the original structure  \n      - **`type?: PropertyType`** - type of the original property  \n      - **`usageType?: PropertyType`** - type for usage property  \n      - **`arrayType?: boolean`** - property have array type or not  \n      - **`optional?: boolean`** - same [from property](#-fieldoptions-fieldoptionssource) options but have more priority\n\n\n  Examples:  \n  ```js\n  const Model = model({\n    someProp: field({\n      name: 'SomeProp',\n      optional: true,\n      type: 'number',\n      usageType: 'string'\n    })\n  })\n\n  const structure = new Model({\n    SomeProp: 12345\n  })\n\n  console.log(structure.someProp) // '12345' because usageType - 'string'\n  console.log(structure.deserialize()) // { SomeProp: 12345 }\n  ```  \n![image](./assets/empty_block.png)  \n\n\n\n\n\n\u003c!-- Function `field()` needs you to describe some property of your model like  \n```\nclass  --\u003e\n\n\u003chr\u003e\n\n\n### 🔹 **`fieldArray()`**[[Source]](./src/field_declaration.ts#L105)  \n\nThis is the same thing like [`field()`](#-fieldoptions-fieldoptionssource) but it needs to describe array of data  \n\n```js\n  const Struct = model({ // it is required wrapper for structure declarations\n    stringsArray: fieldArray('DataArray', 'string')\n    // stringsArray - name of the usage property\n    // 'DataArray' (first arg) - name of the original property which should be array\n    // 'string' (second arg) - type of the each element in array\n  })\n```\n\nArgument variations:  \n\n- **`fieldArray(originalPropertyName: string, originalType?: string, usageType?: string)`**  \n      - **`originalPropertyName`** - name of property which should be exist in original structure  \n      - **`originalType?: string`** - type of the original property.  \n      - **`usageType?: string`** - needed type of the usage property.  \n\n\n- **`fieldArray(originalPropertyName: string, modelDeclaration: ModelDeclaration)`**  \n      - **`originalPropertyName`** - name of property which should be exist in original structure  \n      [`modelDeclaration`](./src/field_declaration.ts#L8) should be `object`/`model(DeclarationsClass)`  \n      And keys/properties should have values created via `field()`, `fieldArray()` function  \n\n\u003chr\u003e\n\n\n### 🔹 `model()`[[Source]](./src/model_wrapper.ts#L48)  \n\nThis function allows to make model from structure declaration.  \nSyntax: \n```js\n  model(YourStructDeclaration: object | class, config?: object)\n\n  // YourStructDeclaration can be:\n\n  YourStructDeclaration = {\n    foo: field('foo')\n  }\n  class YourStructDeclaration {\n    foo = field('foo')\n  }\n\n  // config contains properties:\n  const config = {\n    warnings: boolean // - disable/enable most warnings based on this declaration\n  }\n\n```\n\n\nExamples:  \n```js\n  const Struct = model({ // it is required wrapper for structure declarations\n    // your property declarations\n    firstName: field('FirstName')\n    lastName: field('LastName')\n  })\n```\n\n   \n   \n   \n## 📄 Examples  \n\nAll examples are located [here](./example/index.ts)  \n\n![example of usage 1](./assets/serializy_example.png)\n![example of usage 2](./assets/serializy_example2.png)\n\n\n## 📢 Integrations  \n\n  [**kinka-serializy**](https://github.com/acacode/kinka-serializy) - integration serializy with http web-client [**kinka**](https://github.com/acacode/kinka)  \n  [**axios-serializy**](https://github.com/acacode/axios-serializy) - integration serializy with http web-client [**axios**](https://github.com/axios/axios)\n\n\n## 📝 License\n\nLicensed under the [MIT License](./LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Facacode%2Fserializy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Facacode%2Fserializy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Facacode%2Fserializy/lists"}