@@ -220,6 +220,216 @@ be output as attributes you can specify a whitelist of attributes for each type.
220
220
#### note
221
221
The attributes arrays are keyed by type not by model name. Type is the term used by json api to describe the resource type in question and while not required by json api it is usually plural. In ` loopback-component-jsonapi ` it is whatever the models ` plural ` is set to in ` model.json ` . So in our example above we defined: ` "posts": ["title", "content"] ` as the resource type for the ` post ` model is ` posts `
222
222
223
+ ## Custom Serialization
224
+ For occasions where you need greater control over the serialization process, you can implement a custom serialization function for each model as needed. This function will be used instead of the regular serialization process.
225
+
226
+ #### example
227
+ ``` js
228
+ module .exports = function (MyModel ) {
229
+ MyModel .jsonApiSerialize = function (options , callback ) {
230
+ // either return an error
231
+ var err = new Error (' Unable to serialize record' );
232
+ err .status = 500 ;
233
+ cb (err)
234
+
235
+ // or return serialized records
236
+ if (Array .isArray (options .records )) {
237
+ // serialize an array of records
238
+ } else {
239
+ // serialize a single record
240
+ }
241
+ cb (null , options);
242
+ }
243
+ }
244
+ ```
245
+
246
+ ##### function parameters
247
+
248
+ - ` options ` All config options set for the serialization process. See below.
249
+ - ` callback ` Callback to call with error or serialized records
250
+
251
+ ###### ` options.type `
252
+ Resource type. Originally calculated from a models plural. Is used in the default
253
+ serialization process to set the type property for each model in a jsonapi response.
254
+ - eg. ` posts `
255
+
256
+ ###### ` options.method `
257
+ The method that was called to get the data for the current request. This is not
258
+ used in the serialization process but is provided for custom hook and serialization
259
+ context.
260
+ - Eg. ` create ` , ` updateAttributes `
261
+
262
+ ###### ` options.primaryKeyField `
263
+ The name of the property that is the primary key for the model. This is usually just
264
+ ` id ` unless defined differently in a model.json file.
265
+
266
+ ###### ` options.requestedIncludes `
267
+ The relationships that the user has requested be side loaded with the request.
268
+ For example, for the request ` GET /api/posts?include=comments ` options.requestedIncludes
269
+ would be ` 'comments' ` .
270
+ - Type: ` string ` or ` array `
271
+ - eg: ` 'comments' ` or ` ['posts', 'comments'] `
272
+
273
+ ###### ` options.host `
274
+ The host part of the url including any port information.
275
+ - eg. ` http://localhost:3000 `
276
+
277
+ ###### ` options.restApiRoot `
278
+ The api prefix used before resource information. Can be used in conjunction with
279
+ ` options.host ` and ` options.type ` to build up the full url for a resource.
280
+ - eg. ` /api `
281
+
282
+ ###### ` options.topLevelLinks `
283
+ JSON API links object used at the top level of the JSON API response structure.
284
+ - eg. ` {links: {self: 'http://localhost:3000/api/posts'}} `
285
+
286
+ ###### ` options.dataLinks `
287
+ links object used to generate links for individual resource items. The structure is
288
+ and object with JSON API link keys such as ` self ` or ` related ` that are defined as
289
+ a function that will be called for each resource.
290
+
291
+ Eg.
292
+ ``` js
293
+ options .dataLinks : {
294
+ self : function (resource ) {
295
+ return ' http://localhost:3000/posts/' + resource .id ;
296
+ }
297
+ }
298
+ ```
299
+ As shown above, each resource gets passed to the function and the result of the
300
+ function is assigned to the key in the final JSON API response.
301
+
302
+ ###### ` options.relationships `
303
+ This contains all the relationship definitions for the model being serialized.
304
+ Relationship definition objects are in the same format as in loopback's ` Model.relations `
305
+ definition. An object with relationship name keys, each having properties:
306
+
307
+ - ` modelTo ` loopback model object
308
+ - ` keyTo ` name of key on to model
309
+ - ` modelFrom ` loopback model object
310
+ - ` keyFrom ` name of key on from model
311
+ - ` type ` type of relationship (belongsTo, hasOne, hasMany)
312
+
313
+ This information is used to build relationship urls and even setup side loaded
314
+ data correctly during the serialization process.
315
+
316
+ eg.
317
+ ``` js
318
+ options .relationships = {
319
+ comments: { modelTo: ... etc },
320
+ tags: { modelTo: ... etc }
321
+ }
322
+ ```
323
+
324
+ ###### ` options.results `
325
+ This is the actual data to be serialized. In ` beforeJsonApiSerialize ` and
326
+ ` jsonApiSerialize ` this will be the raw data as you would ordinarily get it from
327
+ loopback. In ` afterJsonApiSerialize ` this will be the serialized data ready for
328
+ any final modifications.
329
+
330
+ ###### ` options.exclude `
331
+ This is the exclude settings as defined in the ` exclude ` configuration option
332
+ explained earlier. Use this in ` beforeJsonApiSerialize ` to make any model specific
333
+ adjustments before serialization.
334
+
335
+ ###### ` options.attributes `
336
+ This is the attributes settings as defined in the ` attributes ` configuration option
337
+ explained earlier. Use this in ` beforeJsonApiSerialize ` to make any model specific
338
+ adjustments before serialization.
339
+
340
+ ## Serialization Hooks
341
+ For occasions when you don't want to fully implement serialization for a model manually but
342
+ you need to manipulate the serialization process, you can use the serialization
343
+ hooks ` beforeJsonApiSerialize ` and ` afterJsonApiSerialize ` .
344
+
345
+ ### beforeJsonApiSerialize
346
+ In order to modify the serialization process on a model by model basis, you can
347
+ define a ` Model.beforeJsonApiSerialize ` function as shown below. The function
348
+ will be called with an options object and a callback which must be called with either
349
+ an error as the first argument or the modified options object as the second
350
+ parameter.
351
+
352
+ ** Examples of things you might want to use this feature for**
353
+ - modify the record(s) before serialization by modifying ` options.results `
354
+ - modify the resource type by modifying ` options.type `
355
+ - setup serialization differently depending on ` options.method `
356
+ - side load data (advanced)
357
+ - modify the way relationships are serialized
358
+
359
+ #### code example
360
+ ``` js
361
+ module .exports = function (MyModel ) {
362
+ MyModel .beforeJsonApiSerialize = function (options , callback ) {
363
+ // either return an error
364
+ var err = new Error (' Unable to serialize record' );
365
+ err .status = 500 ;
366
+ callback (err)
367
+
368
+ // or return modified records
369
+ if (Array .isArray (options .results )) {
370
+ // modify an array of records
371
+ } else {
372
+ // modify a single record
373
+ }
374
+ // returned options.records will be serialized by either the default serialization process
375
+ // or by a custom serialize function (described above) if one is present on the model.
376
+ callback (null , options);
377
+ }
378
+ }
379
+ ```
380
+
381
+ ##### function parameters
382
+ - ` options ` All config options set for the serialization process. See the "function parameters"
383
+ section above for info on what options properties are available for modification.
384
+ - ` callback ` Callback to call with error or options object.
385
+
386
+ #### example use case
387
+ Because the ` beforeJsonApiSerialize ` method is passed all the options that will
388
+ be used during serialization, it is possible to tweak options to affect the
389
+ serialization process. One example of this is modifying the ` type ` option to
390
+ change the resource type that will be output.
391
+
392
+ ``` js
393
+ module .exports = function (MyModel ) {
394
+ MyModel .beforeJsonApiSerialize = function (options , callback ) {
395
+ options .type = ' mycustommodels' ;
396
+ cb (null , options);
397
+ }
398
+ }
399
+ ```
400
+
401
+ ### afterJsonApiSerialize
402
+ In order to modify the serialized data on a model by model basis, you can
403
+ define a ` Model.afterJsonApiSerialize ` function as shown below. The function
404
+ will be called with an options object and a callback which must be called with either
405
+ an error as the first argument or the modified options object as the second
406
+ parameter.
407
+
408
+ #### example
409
+ ``` js
410
+ module .exports = function (MyModel ) {
411
+ MyModel .afterJsonApiSerialize = function (options , callback ) {
412
+ // either return an error
413
+ var err = new Error (' Unable to modify serialized record' );
414
+ err .status = 500 ;
415
+ callback (err)
416
+
417
+ // or return modified records
418
+ if (Array .isArray (options .results )) {
419
+ // modify an array of serialized records
420
+ } else {
421
+ // modify a single serialized record
422
+ }
423
+ // returned options.records will be output through the api.
424
+ callback (null , options);
425
+ }
426
+ }
427
+ ```
428
+
429
+ ##### function parameters
430
+ - ` options ` All config options set for the serialization process
431
+ - ` callback ` Callback to call with modified serialized records
432
+
223
433
## Debugging
224
434
You can enable debug logging by setting an environment variable:
225
435
` DEBUG=loopback-component-jsonapi `
0 commit comments