Topics Validation & Serialization Custom Validation & Serializers
advanced 15 min read

Custom Validation & Serializers

Extend Fastify with custom validators, formatters, and content type parsers.

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 });

Your Notes

Sign in to take notes for this lesson.

Quiz

Validation & Serialization Quiz

0 questions

Sign in to take quiz

Discussion

Sign in to join the discussion.

Flashcards

Sign in to create flashcards.