Custom Content Type Parser
// Parse custom content types\napp.addContentTypeParser('application/vnd.api+json', {\n parseAs: 'string',\n}, (req, body, done) => {\n try {\n const json = JSON.parse(body);\n done(null, json.data);\n } catch (err) {\n done(err);\n }\n});\n\n// Custom validator\napp.setValidatorCompiler(({ schema, method, url, httpPart }) => {\n // httpPart is 'body', 'params', 'querystring', or 'headers'\n return (data) => {\n const valid = Object.keys(schema.properties).every(key => {\n if (schema.required?.includes(key) && data[key] === undefined) {\n return false;\n }\n return true;\n });\n return { valid, errors: valid ? [] : [{ message: 'Validation failed' }] };\n };\n});\n\n// Custom serializer for specific content types\napp.addSerializer('application/json', (data) => {\n return JSON.stringify({\n success: true,\n timestamp: Date.now(),\n data,\n });\n});
AJV Configuration
const app = Fastify({\n ajv: {\n customOptions: {\n coerceTypes: true, // Auto-convert types\n removeAdditional: true, // Strip unknown properties\n useDefaults: true, // Apply default values\n allErrors: true, // Report all validation errors\n },\n plugins: [\n require('ajv-formats'), // Add format validators\n require('ajv-errors'), // Custom error messages\n ],\n },\n});
Examples
const Fastify = require('fastify');
const app = Fastify({
ajv: {
customOptions: {
coerceTypes: 'array',
removeAdditional: true,
useDefaults: true,
allErrors: true,
},
plugins: [require('ajv-formats')],
},
});
// Route with custom validation behavior
app.post('/items', {
schema: {
body: {
type: 'object',
required: ['name', 'price'],
properties: {
name: { type: 'string', minLength: 1 },
price: { type: 'number', minimum: 0 },
tags: {
type: 'array',
items: { type: 'string' },
uniqueItems: true,
},
metadata: {
type: 'object',
additionalProperties: false,
properties: {
color: { type: 'string' },
size: { type: 'string', enum: ['S', 'M', 'L', 'XL'] },
},
},
},
},
},
}, async (request, reply) => {
// coerceTypes: true means '123' becomes 123, 'true' becomes true
// removeAdditional: true strips unknown fields
// useDefaults: true applies default values
return {
received: request.body,
message: 'Item created successfully',
};
});
app.listen({ port: 3000 });