{"id":13694990,"url":"https://github.com/danivek/json-api-serializer","last_synced_at":"2025-04-04T11:10:58.492Z","repository":{"id":4332556,"uuid":"52780216","full_name":"danivek/json-api-serializer","owner":"danivek","description":"Node.js/browser framework agnostic JSON API (http://jsonapi.org/) serializer.","archived":false,"fork":false,"pushed_at":"2023-11-13T10:26:53.000Z","size":699,"stargazers_count":153,"open_issues_count":7,"forks_count":38,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-03-28T10:06:11.435Z","etag":null,"topics":["hypermedia","javascript","json-api","json-api-serializer","jsonapi","jsonapi-serializer","nodejs","serializer"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/danivek.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2016-02-29T09:39:20.000Z","updated_at":"2025-01-28T10:46:28.000Z","dependencies_parsed_at":"2024-03-03T06:43:22.472Z","dependency_job_id":null,"html_url":"https://github.com/danivek/json-api-serializer","commit_stats":{"total_commits":183,"total_committers":20,"mean_commits":9.15,"dds":"0.13661202185792354","last_synced_commit":"eeb32256a56444a5eddfc9b1e7e0f8ffec0866aa"},"previous_names":[],"tags_count":60,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danivek%2Fjson-api-serializer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danivek%2Fjson-api-serializer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danivek%2Fjson-api-serializer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danivek%2Fjson-api-serializer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/danivek","download_url":"https://codeload.github.com/danivek/json-api-serializer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247166168,"owners_count":20894654,"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":["hypermedia","javascript","json-api","json-api-serializer","jsonapi","jsonapi-serializer","nodejs","serializer"],"created_at":"2024-08-02T17:01:55.194Z","updated_at":"2025-04-04T11:10:58.475Z","avatar_url":"https://github.com/danivek.png","language":"JavaScript","readme":"# json-api-serializer\n\n[![build](https://github.com/danivek/json-api-serializer/workflows/build/badge.svg)](https://github.com/danivek/json-api-serializer/actions?query=workflow%3Abuild)\n[![Coverage Status](https://coveralls.io/repos/github/danivek/json-api-serializer/badge.svg?branch=master)](https://coveralls.io/github/danivek/json-api-serializer?branch=master)\n[![npm](https://img.shields.io/npm/v/json-api-serializer.svg)](https://www.npmjs.org/package/json-api-serializer)\n\nA Node.js/browser framework agnostic library for serializing your data to [JSON API](http://jsonapi.org/) compliant responses (a specification for building APIs in JSON).\n\n## Installation\n\n```bash\nnpm install --save json-api-serializer\n```\n\n## Documentation\n\n### Register\n\n```javascript\nvar JSONAPISerializer = require(\"json-api-serializer\");\nvar Serializer = new JSONAPISerializer();\nSerializer.register(type, options);\n```\n\n**Serialization options:**\n\n* **id** (optional): The key to use as the reference. Default = 'id'.\n* **blacklist** (optional): An array of blacklisted attributes. Default = [].\n* **whitelist** (optional): An array of whitelisted attributes. Default = [].\n* **jsonapiObject** (optional): Enable/Disable [JSON API Object](http://jsonapi.org/format/#document-jsonapi-object). Default = true.\n* **links** (optional): Describes the links inside data. It can be:\n  * An _object_ (values can be string or function).\n  * A _function_ with one argument `function(data) { ... }` or with two arguments `function(data, extraData) { ... }`\n* **topLevelMeta** (optional): Describes the top-level meta. It can be:\n  * An _object_ (values can be string or function).\n  * A _function_ with one argument `function(extraData) { ... }` or with two arguments `function(data, extraData) { ... }`\n* **topLevelLinks** (optional): Describes the top-level links. It can be:\n  * An _object_ (values can be string or function).\n  * A _function_ with one argument `function(extraData) { ... }` or with two arguments `function(data, extraData) { ... }`\n* **meta** (optional): Describes resource-level meta. It can be:\n  * An _object_ (values can be string or function).\n  * A _function_ with one argument `function(data) { ... }` or with two arguments `function(data, extraData) { ... }`\n* **relationships** (optional): An object defining some relationships\n  * relationship: The property in data to use as a relationship\n    * **type**: A _string_ or a _function_ `function(relationshipData, data) { ... }` for the type to use for serializing the relationship (type need to be register).\n    * **alternativeKey** (optional): An alternative key (string or path) to use if relationship key not exist (example: 'author_id' as an alternative key for 'author' relationship). See [issue #12](https://github.com/danivek/json-api-serializer/issues/12).\n    * **schema** (optional): A custom schema for serializing the relationship. If no schema define, it use the default one.\n    * **links** (optional): Describes the links for the relationship. It can be:\n      * An _object_ (values can be string or function).\n      * A _function_ with one argument `function(data) { ... }` or with two arguments `function(data, extraData) { ... }`\n    * **meta** (optional): Describes meta that contains non-standard meta-information about the relationship. It can be:\n      * An _object_ (values can be string or function).\n      * A _function_ with one argument `function(data) { ... }` or with two arguments `function(data, extraData) { ... }`\n    * **deserialize** (optional): Describes the function which should be used to deserialize a related property which is not included in the JSON:API document. It should be:\n      * A _function_ with one argument `function(data) { ... }`which defines the format to which a relation should be deserialized. By default, the ID of the related object is returned, which would be equal to `function(data) {return data.id}`. See [issue #65](https://github.com/danivek/json-api-serializer/issues/65).\n* **convertCase** (optional): Case conversion for serializing data. Value can be : `kebab-case`, `snake_case`, `camelCase`\n* **beforeSerialize** (optional): A _function_ with one argument `beforeSerialize(data) =\u003e newData` to transform data before serialization.\n\n**Deserialization options:**\n\n* **unconvertCase** (optional): Case conversion for deserializing data. Value can be : `kebab-case`, `snake_case`, `camelCase`\n* **blacklistOnDeserialize** (optional): An array of blacklisted attributes. Default = [].\n* **whitelistOnDeserialize** (optional): An array of whitelisted attributes. Default = [].\n* **afterDeserialize** (optional): A _function_ with one argument `afterDeserialize(data) =\u003e newData` to transform data after deserialization.\n\n**Global options:**\n\nTo avoid repeating the same options for each type, it's possible to add global options on `JSONAPISerializer` instance:\n\nWhen using convertCase, a LRU cache is utilized for optimization. The default size of the cache is 5000 per conversion type. The size of the cache can be set with the `convertCaseCacheSize` option. Passing in 0 will result in a LRU cache of infinite size.\n\n```javascript\nvar JSONAPISerializer = require(\"json-api-serializer\");\nvar Serializer = new JSONAPISerializer({\n  convertCase: \"kebab-case\",\n  unconvertCase: \"camelCase\",\n  convertCaseCacheSize: 0\n});\n```\n\n## Usage\n\ninput data (can be an object or an array of objects)\n\n```javascript\n// Data\nvar data = [\n  {\n    id: \"1\",\n    title: \"JSON API paints my bikeshed!\",\n    body: \"The shortest article. Ever.\",\n    created: \"2015-05-22T14:56:29.000Z\",\n    updated: \"2015-05-22T14:56:28.000Z\",\n    author: {\n      id: \"1\",\n      firstName: \"Kaley\",\n      lastName: \"Maggio\",\n      email: \"Kaley-Maggio@example.com\",\n      age: \"80\",\n      gender: \"male\"\n    },\n    tags: [\"1\", \"2\"],\n    photos: [\n      \"ed70cf44-9a34-4878-84e6-0c0e4a450cfe\",\n      \"24ba3666-a593-498c-9f5d-55a4ee08c72e\",\n      \"f386492d-df61-4573-b4e3-54f6f5d08acf\"\n    ],\n    comments: [\n      {\n        _id: \"1\",\n        body: \"First !\",\n        created: \"2015-08-14T18:42:16.475Z\"\n      },\n      {\n        _id: \"2\",\n        body: \"I Like !\",\n        created: \"2015-09-14T18:42:12.475Z\"\n      },\n      {\n        _id: \"3\",\n        body: \"Awesome\",\n        created: \"2015-09-15T18:42:12.475Z\"\n      }\n    ]\n  }\n];\n```\n\n### Register\n\nRegister your resources types :\n\n```javascript\nvar JSONAPISerializer = require(\"json-api-serializer\");\nvar Serializer = new JSONAPISerializer();\n\n// Register 'article' type\nSerializer.register(\"article\", {\n  id: \"id\", // The attributes to use as the reference. Default = 'id'.\n  blacklist: [\"updated\"], // An array of blacklisted attributes. Default = []\n  links: {\n    // An object or a function that describes links.\n    self: function(data) {\n      // Can be a function or a string value ex: { self: '/articles/1'}\n      return \"/articles/\" + data.id;\n    }\n  },\n  relationships: {\n    // An object defining some relationships.\n    author: {\n      type: \"people\", // The type of the resource\n      links: function(data) {\n        // An object or a function that describes Relationships links\n        return {\n          self: \"/articles/\" + data.id + \"/relationships/author\",\n          related: \"/articles/\" + data.id + \"/author\"\n        };\n      }\n    },\n    tags: {\n      type: \"tag\"\n    },\n    photos: {\n      type: \"photo\"\n    },\n    comments: {\n      type: \"comment\",\n      schema: \"only-body\" // A custom schema\n    }\n  },\n  topLevelMeta: function(data, extraData) {\n    // An object or a function that describes top level meta.\n    return {\n      count: extraData.count,\n      total: data.length\n    };\n  },\n  topLevelLinks: {\n    // An object or a function that describes top level links.\n    self: \"/articles\" // Can be a function (with extra data argument) or a string value\n  }\n});\n\n// Register 'people' type\nSerializer.register(\"people\", {\n  id: \"id\",\n  links: {\n    self: function(data) {\n      return \"/peoples/\" + data.id;\n    }\n  }\n});\n\n// Register 'tag' type\nSerializer.register(\"tag\", {\n  id: \"id\"\n});\n\n// Register 'photo' type\nSerializer.register(\"photo\", {\n  id: \"id\"\n});\n\n// Register 'comment' type with a custom schema\nSerializer.register(\"comment\", \"only-body\", {\n  id: \"_id\"\n});\n```\n\n### Serialize\n\nSerialize it with the corresponding resource type, data and optional extra data :\n\n```javascript\n// Synchronously (blocking)\nconst result = Serializer.serialize('article', data, {count: 2});\n\n// Asynchronously (non-blocking)\nSerializer.serializeAsync('article', data, {count: 2})\n  .then((result) =\u003e {\n    ...\n  });\n```\n\nThe output data will be :\n\n```JSON\n{\n  \"jsonapi\": {\n    \"version\": \"1.0\"\n  },\n  \"meta\": {\n    \"count\": 2,\n    \"total\": 1\n  },\n  \"links\": {\n    \"self\": \"/articles\"\n  },\n  \"data\": [{\n    \"type\": \"article\",\n    \"id\": \"1\",\n    \"attributes\": {\n      \"title\": \"JSON API paints my bikeshed!\",\n      \"body\": \"The shortest article. Ever.\",\n      \"created\": \"2015-05-22T14:56:29.000Z\"\n    },\n    \"relationships\": {\n      \"author\": {\n        \"data\": {\n          \"type\": \"people\",\n          \"id\": \"1\"\n        },\n        \"links\": {\n          \"self\": \"/articles/1/relationships/author\",\n          \"related\": \"/articles/1/author\"\n        }\n      },\n      \"tags\": {\n        \"data\": [{\n          \"type\": \"tag\",\n          \"id\": \"1\"\n        }, {\n          \"type\": \"tag\",\n          \"id\": \"2\"\n        }]\n      },\n      \"photos\": {\n        \"data\": [{\n          \"type\": \"photo\",\n          \"id\": \"ed70cf44-9a34-4878-84e6-0c0e4a450cfe\"\n        }, {\n          \"type\": \"photo\",\n          \"id\": \"24ba3666-a593-498c-9f5d-55a4ee08c72e\"\n        }, {\n          \"type\": \"photo\",\n          \"id\": \"f386492d-df61-4573-b4e3-54f6f5d08acf\"\n        }]\n      },\n      \"comments\": {\n        \"data\": [{\n          \"type\": \"comment\",\n          \"id\": \"1\"\n        }, {\n          \"type\": \"comment\",\n          \"id\": \"2\"\n        }, {\n          \"type\": \"comment\",\n          \"id\": \"3\"\n        }]\n      }\n    },\n    \"links\": {\n      \"self\": \"/articles/1\"\n    }\n  }],\n  \"included\": [{\n    \"type\": \"people\",\n    \"id\": \"1\",\n    \"attributes\": {\n      \"firstName\": \"Kaley\",\n      \"lastName\": \"Maggio\",\n      \"email\": \"Kaley-Maggio@example.com\",\n      \"age\": \"80\",\n      \"gender\": \"male\"\n    },\n    \"links\": {\n      \"self\": \"/peoples/1\"\n    }\n  }, {\n    \"type\": \"comment\",\n    \"id\": \"1\",\n    \"attributes\": {\n      \"body\": \"First !\"\n    }\n  }, {\n    \"type\": \"comment\",\n    \"id\": \"2\",\n    \"attributes\": {\n      \"body\": \"I Like !\"\n    }\n  }, {\n    \"type\": \"comment\",\n    \"id\": \"3\",\n    \"attributes\": {\n      \"body\": \"Awesome\"\n    }\n  }]\n}\n```\n\nThere is an available argument `excludeData` that will exclude the `data`\nproperty from the serialized object. This can be used in cases where you may\nwant to only include the `topLevelMeta` in your response, such as a `DELETE`\nresponse with only a `meta` property, or other cases defined in the\nJSON:API spec.\n\n```javascript\n// Synchronously (blocking)\nconst result = Serializer.serialize('article', data, 'default', {count: 2}, true);\n\n// Asynchronously (non-blocking)\nSerializer.serializeAsync('article', data, 'default', {count: 2}, true)\n  .then((result) =\u003e {\n    ...\n  });\n```\n\n#### Override schema options\n\nOn each individual call to `serialize` or `serializeAsync`, there is an parameter to override the options of any registered type. For example on a call to serialize, if a whitelist was not defined on the registered schema options, a whitelist (or any other options) for that type can be provided. This parameter is an object, where the key are the registered type names, and the values are the objects to override the registered schema.\n\nIn the following example, only the attribute `name` will be serialized on the article, and if there is a relationship for `person`, it will be serialized with `camelCase` even if the registered schema has a different value.\n```\nconst result = Serializer.serialize('article', data, 'default', {count: 2}, true), {\n  article: {\n    whitelist: ['name']\n  },\n  person: {\n    convertCase: 'camelCase'\n  }\n};\n```\n\n\nSome others examples are available in [tests folders](https://github.com/danivek/json-api-serializer/blob/master/test/)\n\n### Deserialize\n\ninput data (can be an simple object or an array of objects)\n\n```javascript\nvar data = {\n  data: {\n    type: 'article',\n    id: '1',\n    attributes: {\n      title: 'JSON API paints my bikeshed!',\n      body: 'The shortest article. Ever.',\n      created: '2015-05-22T14:56:29.000Z'\n    },\n    relationships: {\n      author: {\n        data: {\n          type: 'people',\n          id: '1'\n        }\n      },\n      comments: {\n        data: [{\n          type: 'comment',\n          id: '1'\n        }, {\n          type: 'comment',\n          id: '2'\n        }]\n      }\n    }\n  }\n};\n\n// Synchronously (blocking)\nSerializer.deserialize('article', data);\n\n// Asynchronously (non-blocking)\nSerializer.deserializeAsync('article', data)\n  .then((result) =\u003e {\n    // ...\n  });\n```\n\n```JSON\n{\n  \"id\": \"1\",\n  \"title\": \"JSON API paints my bikeshed!\",\n  \"body\": \"The shortest article. Ever.\",\n  \"created\": \"2015-05-22T14:56:29.000Z\",\n  \"author\": \"1\",\n  \"comments\": [\n    \"1\",\n    \"2\"\n  ]\n}\n```\n\n### serializeError\n\nSerializes any error into a JSON API error document.\n\nInput data can be:\n  - An instance of `Error` or an array of `Error` instances.\n  - A [JSON API error object](http://jsonapi.org/format/#error-objects) or an array of [JSON API error objects](http://jsonapi.org/format/#error-objects).\n\nUsing an instance of `Error`:\n\n```javascript\nconst error = new Error('An error occurred');\nerror.id = 123\nerror.links = { about: 'https://example.com/errors/123' }\nerror.status = 500; // or `statusCode`\nerror.code = 'xyz'\nerror.meta = { time: Date.now() }\n\nSerializer.serializeError(error);\n```\n\nThe result will be:\n\n```JSON\n{\n  \"errors\": [\n    {\n      \"id\": 123,\n      \"links\": {\n        \"about\": \"https://example.com/errors/123\"\n      },\n      \"status\": \"500\",\n      \"code\": \"xyz\",\n      \"title\": \"Error\",\n      \"detail\": \"An error occurred\",\n      \"meta\": {\n        \"time\": 1593561258853\n      }\n    }\n  ]\n}\n```\n\nUsing an instance of a class that inherits from `Error`:\n\n```js\nclass MyCustomError extends Error {\n  constructor(message = 'Something went wrong') {\n    super(message)\n    this.id = 123\n    this.links = {\n      about: 'https://example.com/errors/123'\n    }\n    this.status = 500 // or `statusCode`\n    this.code = 'xyz'\n    this.meta = {\n      time: Date.now()\n    }\n  }\n}\n\nSerializer.serializeError(new MyCustomError());\n```\n\nThe result will be:\n\n```JSON\n{\n  \"errors\": [\n    {\n      \"id\": 123,\n      \"links\": {\n        \"about\": \"https://example.com/errors/123\"\n      },\n      \"status\": \"500\",\n      \"code\": \"xyz\",\n      \"title\": \"MyCustomError\",\n      \"detail\": \"Something went wrong\",\n      \"meta\": {\n        \"time\": 1593561258853\n      }\n    }\n  ]\n}\n```\n\nUsing a POJO:\n\n```js\nSerializer.serializeError({\n  id: 123,\n  links: {\n    about: 'https://example.com/errors/123'\n  },\n  status: 500, // or `statusCode`\n  code: 'xyz',\n  title: 'UserNotFound',\n  detail: 'Unable to find a user with the provided ID',\n  meta: {\n    time: Date.now()\n  }\n});\n```\n\nThe result will be:\n\n```JSON\n{\n  \"errors\": [\n    {\n      \"id\": 123,\n      \"links\": {\n        \"about\": \"https://example.com/errors/123\"\n      },\n      \"status\": \"500\",\n      \"code\": \"xyz\",\n      \"title\": \"UserNotFound\",\n      \"detail\": \"Unable to find a user with the provided ID\",\n      \"meta\": {\n        \"time\": 1593561258853\n      }\n    }\n  ]\n}\n```\n\n## Custom schemas\n\nIt is possible to define multiple custom schemas for a resource type :\n\n```javascript\nSerializer.register(type, \"customSchema\", options);\n```\n\nThen you can apply this schema on the primary data when serialize or deserialize :\n\n```javascript\nSerializer.serialize(\"article\", data, \"customSchema\", { count: 2 });\nSerializer.serializeAsync(\"article\", data, \"customSchema\", { count: 2 });\nSerializer.deserialize(\"article\", jsonapiData, \"customSchema\");\nSerializer.deserializeAsync(\"article\", jsonapiData, \"customSchema\");\n```\n\nOr if you want to apply this schema on a relationship data, define this schema on relationships options with the key `schema` :\n\nExample :\n\n```javascript\nrelationships: {\n  comments: {\n    type: \"comment\";\n    schema: \"customSchema\";\n  }\n}\n```\n\n## Mixed data (dynamic type)\n\n### Serialize\n\nIf your data contains one or multiple objects of different types, it's possible to define a configuration object instead of the type-string as the first argument of `serialize` and `serializeAsync` with these options:\n\n* **type** (required): A _string_ for the path to the key to use to determine type or a _function_ deriving a type-string from each data-item.\n* **jsonapiObject** (optional): Enable/Disable [JSON API Object](http://jsonapi.org/format/#document-jsonapi-object). Default = true.\n* **topLevelMeta** (optional): Describes the top-level meta. It can be:\n  * An _object_ (values can be string or function).\n  * A _function_ with one argument `function(extraData) { ... }` or with two arguments `function(data, extraData) { ... }`\n* **topLevelLinks** (optional): Describes the top-level links. It can be:\n  * An _object_ (values can be string or function).\n  * A _function_ with one argument `function(extraData) { ... }` or with two arguments `function(data, extraData) { ... }`\n\nExample :\n\n```javascript\nconst typeConfig = {\n  // Same as type: 'type'\n  type: data =\u003e data.type // Can be very complex to determine different types of items.\n};\n\nSerializer.serializeAsync(typeConfig, data, { count: 2 }).then(result =\u003e {\n  // ...\n});\n```\n\n### Deserialize\n\nIf your data contains one or multiple objects of different types, it's possible to define a configuration object instead of the type-string as the first argument of `deserialize` with these options:\n\n* **type** (required): A _string_ for the path to the key to use to determine type or a _function_ deriving a type-string from each data-item.\n\nExample :\n\n```javascript\nconst typeConfig = {\n  // Same as type: 'type'\n  type: data =\u003e data.type // Can be very complex to determine different types of items.\n};\n\nconst deserialized = Serializer.deserializeAsync(typeConfig, data).then(result =\u003e {\n  // ...\n});\n```\n\n## Custom serialization and deserialization\n\nIf your data requires some specific transformations, those can be applied using `beforeSerialize` and `afterDeserialize`\n\nExample for composite primary keys:\n\n```javascript\nSerializer.register('translation', {\n    beforeSerialize: (data) =\u003e {\n      // Exclude pk1 and pk2 from data\n      const { pk1, pk2, ...attributes } = data;\n\n      // Compute external id\n      const id = `${pk1}-${pk2}`;\n\n      // Return data with id\n      return {\n        ...attributes,\n        id\n      };\n    },\n    afterDeserialize: (data) =\u003e {\n      // Exclude id from data\n      const { id, ...attributes } = data;\n\n      // Recover PKs\n      const [pk1, pk2] = id.split('-');\n\n      // Return data with PKs\n      return {\n        ...attributes,\n        pk1,\n        pk2,\n      };\n    },\n});\n```\n\n## Benchmark\n\n```bash\nPlatform info:\n==============\nDarwin 21.6.0 x64\nNode.JS: 20.9.0\nV8: 11.3.244.8-node.16\nIntel(R) Core(TM) i7-4770HQ CPU @ 2.20GHz × 8\n\nSuite:\n==============\nserializeAsync x 17,846 ops/sec ±1.38% (79 runs sampled)\nserialize x 147,769 ops/sec ±0.54% (93 runs sampled)\nserializeConvertCase x 111,373 ops/sec ±0.72% (96 runs sampled)\ndeserializeAsync x 20,925 ops/sec ±1.39% (78 runs sampled)\ndeserialize x 271,116 ops/sec ±0.32% (95 runs sampled)\ndeserializeConvertCase x 109,091 ops/sec ±0.32% (96 runs sampled)\nserializeError x 105,983 ops/sec ±0.71% (93 runs sampled)\nserializeError with a JSON API error object x 7,431,126 ops/sec ±0.47% (92 runs sampled)\n```\n\n## License\n\n[MIT](https://github.com/danivek/json-api-serializer/blob/master/LICENSE)\n","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanivek%2Fjson-api-serializer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdanivek%2Fjson-api-serializer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanivek%2Fjson-api-serializer/lists"}