Learn about me or read more of my blog
Written by Giulio Canti on 15 Sep 2014
In the last post (JSON Deserialization Into An Object Model) I’ve showed a good solution for consuming a JSON API on the client, but what about the server?
While on the client type checking is a plus (especially in development), on the server the matter is more critical:
In this post I’ll show you how this work can be done in a few lines of code and with the bonus of providing a contract to your API users, with the help of tcomb-validation.
tcomb-validation is a a general purpose JavaScript validation library based on type combinators.
Say you have a sign up API receiving in post a JSON like this:
{
"username": "giulio", // a required string
"password": "secret", // a required string with at least 6 chars
"locale": "it_IT" // optional, one of "it_IT", "en_US"
}
and returning a JSON like this:
{
"id": 1, // a required number
"username": "giulio", // a required string
"locale": "it_IT" // optional, one of "it_IT", "en_US"
}
Let’s write its domain model:
// domain.js
var t = require('tcomb');
// a subtype is a pair (type, predicate)
// where predicate is a function with signature (x) -> boolean
var Password = t.subtype(t.Str, function (s) {
return s.length >= 6;
});
// enum
var Locale = t.enums.of('it_IT en_US');
// a struct is a type containing properties (i.e. a class)
var SignUpInput = t.struct({
username: t.Str, // string type
password: Password,
locale: t.maybe(Locale) // maybe means optional
});
var SignUpOutput = t.struct({
id: t.Num, // number type
username: t.Str,
locale: t.maybe(Locale)
});
module.exports = {
Password: Password,
Locale: Locale,
SignUpInput: SignUpInput,
SignUpOutput: SignUpOutput
};
And now the code of the server application:
// app.js
var express = require('express');
var app = express();
var t = require('tcomb-validation');
var domain = require('./domain');
app.post('/signup', function (req, res) {
var input = JSON.parse(req.body.input);
// one-liner validation
var result = t.validate(input, domain.SignUpInput);
if (result.isValid()) {
// ..your logic here..
// using SignUpOutput it's not mandatory, but enforces the contract
var output = new domain.SignUpOutput({id: 1, username: 'giulio', locale: 'it_IT'});
res.status(200).json(output);
} else {
// in result.errors there are details on the validation failure
res.status(400).json(result.errors);
}
});
As a consequence of what presented in JSON Deserialization Into An Object Model, if you open source the domain.js
file you can provide to your API users a:
minimal JavaScript client.
For a reference of the tcomb-validation library see here on GitHub.