express-serializer
Serialization helper to handle arrays and property filtering for Expressexpress APIs.- Arrays - Passing serialization options - Filtering
- [Filtering with options](#filtering-with-options)
- [Filtering with query parameters](#filtering-with-query-parameters)
- [Filtering complex objects](#filtering-complex-objects)
- [Combining filters](#combining-filters)
Developed at the Media Engineering Institute (HEIG-VD).
Usage
The most basic usage of this module is to call your own serialization functions to serialize objects:const express = require('express');
const serializer = require('express-serializer');
const router = express.Router();
router.get('/api/user', (req, res) => {
// Get an object to serialize.
const user = {
first_name: 'John',
last_name: 'Doe',
birth_date: new Date()
};
// Write your own custom serialization function
// or use your favorite ORM.
function serializeUser(req, user) {
return {
firstName: user.first_name,
lastName: user.last_name,
age: new Date().getFullYear() - user.getFullYear()
};
}
// Call the serializer; it always returns a promise
// (your serialization function can return a promise too).
serialize(req, user, serializeUser).then(json => {
res.send(json);
// HTTP/1.1 200 OK
// Content-Type: application/json
//
// {
// "firstName": "John",
// "lastName": "Doe",
// "age": 42
// }
}).catch(next);
});
Arrays
Now for the interesting part. It will automatically serialize each object in an array:// Get an array of objects to serialize.
const users = [
{
first_name: 'John',
last_name: 'Doe',
birth_date: new Date()
},
{
first_name: 'Bob',
last_name: 'Smith',
birth_date: new Date()
}
];
// Use the same serialization function as before.
function serializeUser(req, user) {
return {
firstName: user.first_name,
lastName: user.last_name,
age: new Date().getFullYear() - user.getFullYear()
};
}
// Each object in the array will be serialized with your function.
serialize(req, users, serializeUser).then(json => {
res.send(json);
// HTTP/1.1 200 OK
// Content-Type: application/json
//
// [
// {
// "firstName": "John",
// "lastName": "Doe",
// "age": 42
// },
// {
// "firstName": "Bob",
// "lastName": "Smith",
// "age": 24
// }
// ]
});
Passing serialization options
Any additional options passed to the serializer as the fourth argument will also be passed to your serialization function:function serializeUser(req, user, options) {
const serialized = {
name: `${user.first_name} ${user.last_name}`
};
// Use options to customize the behavior of your serialization function.
if (options && options.includeBirthDate) {
serialized.birthDate = user.birth_date
}
return serialized;
}
// Call the serializer with options.
const options = { includeBirthDate: true };
serialize(req, user, serializeUser, options).then(json => {
res.send(json);
// HTTP/1.1 200 OK
// Content-Type: application/json
//
// {
// "name": "John Doe",
// "birthDate": "2000-01-01T00:00:00Z"
// }
});
Filtering
Properties of serialized objects can be whitelisted or blacklisted with theonly
and except
options.Filtering with options
only
and except
can be passed in the serialization options:const user = {
first_name: 'John',
last_name: 'Doe',
birth_date: new Date()
};
function serializeUser(req, user) {
return {
firstName: user.first_name,
lastName: user.last_name,
age: new Date().getFullYear() - user.getFullYear()
};
}
// Pick only the first name:
serialize(req, user, serializeUser, { only: 'firstName' }).then(json => {
res.send(json);
// HTTP/1.1 200 OK
// Content-Type: application/json
//
// {
// "firstName": "John"
// }
});
// Pick both the first and last names:
serialize(req, user, serializeUser, { only: [ 'firstName', 'lastName' ] }).then(json => {
res.send(json);
// HTTP/1.1 200 OK
// Content-Type: application/json
//
// {
// "firstName": "John",
// "lastName": "Doe"
// }
});
// Omit the last name:
serialize(req, user, serializeUser, { except: 'lastName' }).then(json => {
res.send(json);
// HTTP/1.1 200 OK
// Content-Type: application/json
//
// {
// "firstName": "John",
// "age": 42
// }
});
Filtering with query parameters
Theonly
and except
query parameters have the same effect if present in the HTTP request:// Pick only the first name:
//
// GET /api/user?only=firstName HTTP/1.1
// Accept: application/json
serialize(req, user, serializeUser).then(json => {
res.send(json);
// HTTP/1.1 200 OK
// Content-Type: application/json
//
// {
// "firstName": "John"
// }
});
// Pick both the first and last names:
//
// GET /api/user?only=firstName&only=lastName HTTP/1.1
// Accept: application/json
serialize(req, user, serializeUser).then(json => {
res.send(json);
// HTTP/1.1 200 OK
// Content-Type: application/json
//
// {
// "firstName": "John",
// "lastName": "Doe"
// }
});
// Omit the last name:
//
// GET /api/user?except=lastName HTTP/1.1
// Accept: application/json
serialize(req, user, serializeUser).then(json => {
res.send(json);
// HTTP/1.1 200 OK
// Content-Type: application/json
//
// {
// "firstName": "John",
// "age": 42
// }
});
Filtering complex objects
You can use a dotted notation inonly
and except
to filter properties of more complex objects:const user = {
first_name: 'John',
last_name: 'Doe',
address: {
city: 'Sunnydale',
state: 'California'
}
};
function serializeUser(req, user) {
return {
firstName: user.first_name,
lastName: user.last_name,
address: user.address
};
}
// Pick only the last name and city:
const options = {
only: [ 'lastName', 'address.city' ]
};
serialize(req, user, serializeUser, options).then(json => {
res.send(json);
// HTTP/1.1 200 OK
// Content-Type: application/json
//
// {
// "firstName": "John",
// "address": {
// "city": "Sunnydale"
// }
// }
});
// Omit the last name and city through query parameters:
//
// GET /api/user?except=lastName&except=address.city HTTP/1.1
// Accept: application/json
serialize(req, user, serializeUser).then(json => {
res.send(json);
// HTTP/1.1 200 OK
// Content-Type: application/json
//
// {
// "firstName": "John",
// "address": {
// "state": "California"
// }
// }
});
Combining filters
Properties which are both inonly
and except
are not included in the serialized object:// Pick only the first and last names,
// and omit the last name and city:
const options = {
only: [ 'firstName', 'lastName' ],
except: [ 'lastName', 'address.city' ]
};
serialize(req, user, serializeUser, options).then(json => {
res.send(json);
// HTTP/1.1 200 OK
// Content-Type: application/json
//
// {
// "firstName": "John",
// "address": {
// "state": "California"
// }
// }
});
If
only
and except
are specified both in the options and in query parameters, they are merged:// Pick only the first and last names through options,
// and omit the first name through query parameters:
//
// GET /api/user?except=firstName HTTP/1.1
// Accept: application/json
const options = {
only: [ 'firstName', 'lastName' ]
};
serialize(req, user, serializeUser, options).then(json => {
res.send(json);
// HTTP/1.1 200 OK
// Content-Type: application/json
//
// {
// "lastName": "Doe"
// }
});
If
except
is present in both the options and in query parameters, the union of all except
properties is used:// Omit the first and last names through options, and omit the state through query parameters:
//
// GET /api/user?except=address.state HTTP/1.1
// Accept: application/json
const options = {
only: [ 'firstName', 'lastName' ]
};
serialize(req, user, serializeUser, options).then(json => {
res.send(json);
// HTTP/1.1 200 OK
// Content-Type: application/json
//
// {
// "address": {
// "city": "Sunnydale"
// }
// }
});
If
only
is present in both the options and in query parameters, the intersection of all only
properties is used:// Pick the first and last names through options,
// and pick the first name through query parameters:
//
// GET /api/user?only=firstName HTTP/1.1
// Accept: application/json
const options = {
only: [ 'firstName', 'lastName' ]
};
serialize(req, user, serializeUser, options).then(json => {
res.send(json);
// HTTP/1.1 200 OK
// Content-Type: application/json
//
// {
// "firstName": "John"
// }
});