1 | # JSON API Serializer
|
2 |
|
3 | <p align="center">
|
4 | <img src="https://github.com/SeyZ/jsonapi-serializer/blob/master/logo.jpg?raw=true" alt="JSONAPI Serializer Logo">
|
5 | </p>
|
6 |
|
7 | [![Build Status](https://travis-ci.org/SeyZ/jsonapi-serializer.svg?branch=master)](https://travis-ci.org/SeyZ/jsonapi-serializer)
|
8 | [![npm version](https://img.shields.io/npm/v/jsonapi-serializer.svg)](https://yarnpkg.com/en/package/jsonapi-serializer)
|
9 | [![download](https://img.shields.io/npm/dm/jsonapi-serializer.svg)](https://yarnpkg.com/en/package/jsonapi-serializer)
|
10 |
|
11 | A Node.js framework agnostic library for (de)serializing your data to [JSON
|
12 | API](http://jsonapi.org) (1.0 compliant).
|
13 |
|
14 | - [Migrate from 2.0 to 3.0](https://github.com/SeyZ/jsonapi-serializer/wiki/Migrate-from-2.0-to-3.0)
|
15 | - [Migrate from 1.x to 2.0](https://github.com/SeyZ/jsonapi-serializer/wiki/Migrate-from-1.x-to-2.0)
|
16 |
|
17 | ## Installation
|
18 | `$ npm install jsonapi-serializer`
|
19 |
|
20 | ## Documentation
|
21 |
|
22 | ### Serialization
|
23 |
|
24 | var JSONAPISerializer = require('jsonapi-serializer').Serializer;
|
25 | new JSONAPISerializer(type, opts).serialize(data);
|
26 |
|
27 | The function `JSONAPISerializer` takes two arguments:
|
28 |
|
29 | - `type`: The resource type.
|
30 | - `opts`: The serialization options.
|
31 |
|
32 | Calling the `serialize` method on the returned object will serialize your `data` (object or array) to a compliant JSONAPI document.
|
33 |
|
34 |
|
35 | #### Available serialization option (`opts` argument)
|
36 |
|
37 | - **attributes**: An array of attributes to show. You can define an attribute as an option if you want to define some relationships (included or not).
|
38 | - **ref**: If present, it's considered as a relationships.
|
39 | - **included**: Consider the relationships as [compound document](http://jsonapi.org/format/#document-compound-documents). Default: true.
|
40 | - **id**: Configurable identifier field for the resource. Default: `id`.
|
41 | - **attributes**: An array of attributes to show.
|
42 | - **topLevelLinks**: An object that describes the top-level links. Values can be *string* or a *function*
|
43 | - **dataLinks**: An object that describes the links inside data. Values can be *string* or a *function* (see examples below)
|
44 | - **dataMeta**: An object that describes the meta inside data. Values can be a plain value or a *function* (see examples below)
|
45 | - **relationshipLinks**: An object that describes the links inside relationships. Values can be *string* or a *function*
|
46 | - **relationshipMeta**: An object that describes the meta inside relationships. Values can be a plain value or a *function*
|
47 | - **ignoreRelationshipData**: Do not include the `data` key inside the relationship. Default: false.
|
48 | - **keyForAttribute**: A function or string to customize attributes. Functions are passed the attribute as a single argument and expect a string to be returned. Strings are aliases for inbuilt functions for common case conversions. Options include: `dash-case` (default), `lisp-case`, `spinal-case`, `kebab-case`, `underscore_case`, `snake_case`, `camelCase`, `CamelCase`.
|
49 | - **nullIfMissing**: Set the attribute to null if missing from your data input. Default: false.
|
50 | - **pluralizeType**: A boolean to indicate if the type must be pluralized or not. Default: true.
|
51 | - **typeForAttribute**: A function that maps the attribute (passed as an argument) to the type you want to override. If it returns `undefined`, ignores the flag for that attribute. Option *pluralizeType* ignored if set.
|
52 | - **meta**: An object to include non-standard meta-information. Values can be a plain value or a *function*
|
53 | - **transform**: A function to transform each record before the serialization.
|
54 |
|
55 | **Examples**
|
56 |
|
57 | - [Express example](https://github.com/SeyZ/jsonapi-serializer/tree/master/examples/express)
|
58 | - [Simple usage](#simple-usage-serializer)
|
59 | - [More examples in tests](https://github.com/SeyZ/jsonapi-serializer/blob/master/test/serializer.js)
|
60 |
|
61 | <a name="simple-usage-serializer"></a>
|
62 | Simple usage:
|
63 |
|
64 | ```javascript
|
65 | var data = [
|
66 | { id: 1, firstName: 'Sandro', lastName: 'Munda' },
|
67 | { id: 2, firstName: 'John', lastName: 'Doe' }
|
68 | ];
|
69 | ```
|
70 |
|
71 | ```javascript
|
72 | var JSONAPISerializer = require('jsonapi-serializer').Serializer;
|
73 |
|
74 | var UserSerializer = new JSONAPISerializer('users', {
|
75 | attributes: ['firstName', 'lastName']
|
76 | });
|
77 |
|
78 | var users = UserSerializer.serialize(data);
|
79 |
|
80 | // `users` here are JSON API compliant.
|
81 | ```
|
82 |
|
83 | The result will be something like:
|
84 |
|
85 | ```javascript
|
86 | {
|
87 | "data": [{
|
88 | "type": "users",
|
89 | "id": "1",
|
90 | "attributes": {
|
91 | "first-name": "Sandro",
|
92 | "last-name": "Munda"
|
93 | }
|
94 | }, {
|
95 | "type": "users",
|
96 | "id": "2",
|
97 | "attributes": {
|
98 | "first-name": "John",
|
99 | "last-name": "Doe"
|
100 | }
|
101 | }]
|
102 | }
|
103 | ```
|
104 |
|
105 | ### Deserialization
|
106 |
|
107 | var JSONAPIDeserializer = require('jsonapi-serializer').Deserializer;
|
108 | new JSONAPIDeserializer(opts).deserialize(data);
|
109 |
|
110 | The function `JSONAPIDeserializer` takes one argument:
|
111 |
|
112 | - `opts`: The deserializer options.
|
113 |
|
114 | Calling the `deserialize` method on the returned object will deserialize your `data` (JSONAPI document) to a plain javascript object.
|
115 |
|
116 | #### Available deserialization option (`opts` argument)
|
117 |
|
118 | - **keyForAttribute**: A function or string to customize attributes. Functions are passed the attribute as a single argument and expect a string to be returned. Strings are aliases for inbuilt functions for common case conversions. Options include: `dash-case` (default), `lisp-case`, `spinal-case`, `kebab-case`, `underscore_case`, `snake_case`, `camelCase`, `CamelCase`.
|
119 | - **AN\_ATTRIBUTE\_TYPE**: this option name corresponds to the type of a relationship from your JSONAPI document.
|
120 | - **valueForRelationship**: A function that returns whatever you want for a relationship (see examples below) ***can return a Promise (see tests)***
|
121 | - **transform**: A function to transform each record after the deserialization.
|
122 |
|
123 | **Examples**
|
124 |
|
125 | - [Simple usage](#simple-usage-deserializer)
|
126 | - [Relationship](#relationship-deserializer)
|
127 | - [More examples in tests](https://github.com/SeyZ/jsonapi-serializer/blob/master/test/deserializer.js)
|
128 |
|
129 | <a name="simple-usage-deserializer"></a>
|
130 | Simple usage:
|
131 |
|
132 | ```
|
133 | {
|
134 | data: [{
|
135 | type: 'users',
|
136 | id: '1',
|
137 | attributes: {
|
138 | 'first-name': Sandro,
|
139 | 'last-name': Munda
|
140 | }
|
141 | }, {
|
142 | type: 'users',
|
143 | id: '2',
|
144 | attributes: {
|
145 | 'first-name': 'John',
|
146 | 'last-name': 'Doe'
|
147 | }
|
148 | }]
|
149 | }
|
150 | ```
|
151 |
|
152 | ```javascript
|
153 | var JSONAPIDeserializer = require('jsonapi-serializer').Deserializer;
|
154 |
|
155 | new JSONAPIDeserializer().deserialize(jsonapi, function (err, users) {
|
156 | // `users` is...
|
157 | });
|
158 | ```
|
159 |
|
160 | ```javascript
|
161 | [
|
162 | { id: 1, firstName: 'Sandro', lastName: 'Munda' },
|
163 | { id: 2, firstName: 'John', lastName: 'Doe' }
|
164 | ];
|
165 | ```
|
166 | <a name="relationship-deserializer"></a>
|
167 | Relationship:
|
168 |
|
169 | ```
|
170 | {
|
171 | data: [{
|
172 | type: 'users',
|
173 | id: '54735750e16638ba1eee59cb',
|
174 | attributes: {
|
175 | 'first-name': 'Sandro',
|
176 | 'last-name': 'Munda'
|
177 | },
|
178 | relationships: {
|
179 | address: {
|
180 | data: { type: 'addresses', id: '54735722e16620ba1eee36af' }
|
181 | }
|
182 | }
|
183 | }, {
|
184 | type: 'users',
|
185 | id: '5490143e69e49d0c8f9fc6bc',
|
186 | attributes: {
|
187 | 'first-name': 'Lawrence',
|
188 | 'last-name': 'Bennett'
|
189 | },
|
190 | relationships: {
|
191 | address: {
|
192 | data: { type: 'addresses', id: '54735697e16624ba1eee36bf' }
|
193 | }
|
194 | }
|
195 | }]
|
196 | }
|
197 | ```
|
198 |
|
199 | ```javascript
|
200 | var JSONAPIDeserializer = require('jsonapi-serializer').Deserializer;
|
201 |
|
202 | new JSONAPIDeserializer({
|
203 | addresses: {
|
204 | valueForRelationship: function (relationship) {
|
205 | return {
|
206 | id: relationship.id,
|
207 | 'address-line1': '406 Madison Court',
|
208 | 'zip-code': '49426',
|
209 | country: 'USA'
|
210 | };
|
211 | }
|
212 | }
|
213 | }).deserialize(jsonapi, function (err, users) {
|
214 | // `users` is...
|
215 | });
|
216 | ```
|
217 |
|
218 | ```
|
219 | [{
|
220 | id: '54735750e16638ba1eee59cb',
|
221 | 'first-name': 'Sandro',
|
222 | 'last-name': 'Munda',
|
223 | address: {
|
224 | id: '54735722e16620ba1eee36af',
|
225 | 'address-line1': '406 Madison Court',
|
226 | 'zip-code': '49426',
|
227 | country: 'USA'
|
228 | }
|
229 | }, {
|
230 | id: '5490143e69e49d0c8f9fc6bc',
|
231 | 'first-name': 'Lawrence',
|
232 | 'last-name': 'Bennett',
|
233 | address: {
|
234 | id: '54735697e16624ba1eee36bf',
|
235 | 'address-line1': '406 Madison Court',
|
236 | 'zip-code': '49426',
|
237 | country: 'USA'
|
238 | }
|
239 | }]
|
240 | ```
|
241 |
|
242 | #### Notes on Promises
|
243 | The deserialization option `valueForRelationship` supports returning a `Promise` and so this library uses `Promises` under the hood. `bluebird` was previously used as a dependency, but due to bundle size concerns on both node and the web it was replaced with native promises.
|
244 |
|
245 | `bluebird` is definitely [more performant](http://bluebirdjs.com/docs/benchmarks.html) than native Promises. If performance is a major concern `Promise` can be globally polyfilled
|
246 | - node - via `global.Promise = require('bluebird')`
|
247 | - web - global `Promise` automatically gets assigned when using the [script tag](http://bluebirdjs.com/docs/getting-started.html) to load `bluebird`
|
248 |
|
249 | ## Error serialization
|
250 |
|
251 | var JSONAPIError = require('jsonapi-serializer').Error;
|
252 | var error = new JSONAPIError(opts);
|
253 |
|
254 | The function JSONAPIError takes one argument:
|
255 |
|
256 | - `opts`: The error options. All options are optional.
|
257 |
|
258 | #### Available error option (`opts` argument)
|
259 |
|
260 | - **id**: a unique identifier for this particular occurrence of the problem.
|
261 | - **status**: the HTTP status code applicable to this problem, expressed as a string value.
|
262 | - **code**: an application-specific error code, expressed as a string value.
|
263 | - **title**: a short, human-readable summary of the problem that SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization.
|
264 | - **detail**: a human-readable explanation specific to this occurrence of the problem. Like title, this field’s value can be localized.
|
265 | - **source**: an object containing references to the source of the error, optionally including any of the following members:
|
266 | - **pointer**: a JSON Pointer [RFC6901] to the associated entity in the request document [e.g. "/data" for a primary data object, or "/data/attributes/title" for a specific attribute].
|
267 | - **parameter**: a string indicating which URI query parameter caused the error.
|
268 | - **links**: a links object containing the following members:
|
269 | - **about**: a link that leads to further details about this particular occurrence of the problem.
|
270 | - **meta**: a meta object containing non-standard meta-information about the error.
|
271 |
|
272 | **Examples**
|
273 |
|
274 | - [Simple usage](#simple-usage-error)
|
275 | - [More example](https://github.com/SeyZ/jsonapi-serializer/blob/master/test/error.js)
|
276 |
|
277 | <a name="simple-usage-error"></a>
|
278 | Simple usage:
|
279 |
|
280 | ```javascript
|
281 | var JSONAPIError = require('jsonapi-serializer').Error;
|
282 |
|
283 | var errors = new JSONAPIError({
|
284 | code: '123',
|
285 | source: { 'pointer': '/data/attributes/first-name' },
|
286 | title: 'Value is too short',
|
287 | detail: 'First name must contain at least three characters.'
|
288 | });
|
289 |
|
290 | // `errors` here are JSON API compliant.
|
291 | ```
|
292 |
|
293 | The result will be something like:
|
294 |
|
295 | ```javascript
|
296 | {
|
297 | "errors": [
|
298 | {
|
299 | "code": "123",
|
300 | "source": { "pointer": "/data/attributes/first-name" },
|
301 | "title": "Value is too short",
|
302 | "detail": "First name must contain at least three characters."
|
303 | }
|
304 | ]
|
305 | }
|
306 | ```
|
307 |
|
308 | # License
|
309 |
|
310 | [MIT](https://github.com/SeyZ/jsonapi-serializer/blob/master/LICENSE)
|