Fluent Schema

The Validation and Serialization documentation outlines all parameters accepted by Fastify to set up JSON Schema Validation to validate the input, and JSON Schema Serialization to optimize the output.

fluent-json-schema can be used to simplify this task while allowing the reuse of constants.

Basic settings

  1. const S = require('fluent-json-schema')
  2. // You can have an object like this, or query a DB to get the values
  3. const MY_KEYS = {
  4. KEY1: 'ONE',
  5. KEY2: 'TWO'
  6. }
  7. const bodyJsonSchema = S.object()
  8. .prop('someKey', S.string())
  9. .prop('someOtherKey', S.number())
  10. .prop('requiredKey', S.array().maxItems(3).items(S.integer()).required())
  11. .prop('nullableKey', S.mixed([S.TYPES.NUMBER, S.TYPES.NULL]))
  12. .prop('multipleTypesKey', S.mixed([S.TYPES.BOOLEAN, S.TYPES.NUMBER]))
  13. .prop('multipleRestrictedTypesKey', S.oneOf([S.string().maxLength(5), S.number().minimum(10)]))
  14. .prop('enumKey', S.enum(Object.values(MY_KEYS)))
  15. .prop('notTypeKey', S.not(S.array()))
  16. const queryStringJsonSchema = S.object()
  17. .prop('name', S.string())
  18. .prop('excitement', S.integer())
  19. const paramsJsonSchema = S.object()
  20. .prop('par1', S.string())
  21. .prop('par2', S.integer())
  22. const headersJsonSchema = S.object()
  23. .prop('x-foo', S.string().required())
  24. // Note that there is no need to call `.valueOf()`!
  25. const schema = {
  26. body: bodyJsonSchema,
  27. querystring: queryStringJsonSchema, // (or) query: queryStringJsonSchema
  28. params: paramsJsonSchema,
  29. headers: headersJsonSchema
  30. }
  31. fastify.post('/the/url', { schema }, handler)

Reuse

With fluent-json-schema you can manipulate your schemas more easily and programmatically and then reuse them thanks to the addSchema() method. You can refer to the schema in two different manners that are detailed in the Validation-and-Serialization.md documentation.

Here are some usage examples:

$ref-way: refer to an external schema.

  1. const addressSchema = S.object()
  2. .id('#address')
  3. .prop('line1').required()
  4. .prop('line2')
  5. .prop('country').required()
  6. .prop('city').required()
  7. .prop('zipcode').required()
  8. const commonSchemas = S.object()
  9. .id('https://fastify/demo')
  10. .definition('addressSchema', addressSchema)
  11. .definition('otherSchema', otherSchema) // You can add any schemas you need
  12. fastify.addSchema(commonSchemas)
  13. const bodyJsonSchema = S.object()
  14. .prop('residence', S.ref('https://fastify/demo#address')).required()
  15. .prop('office', S.ref('https://fastify/demo#/definitions/addressSchema')).required()
  16. const schema = { body: bodyJsonSchema }
  17. fastify.post('/the/url', { schema }, handler)

replace-way: refer to a shared schema to replace before the validation process.

  1. const sharedAddressSchema = {
  2. $id: 'sharedAddress',
  3. type: 'object',
  4. required: ['line1', 'country', 'city', 'zipcode'],
  5. properties: {
  6. line1: { type: 'string' },
  7. line2: { type: 'string' },
  8. country: { type: 'string' },
  9. city: { type: 'string' },
  10. zipcode: { type: 'string' }
  11. }
  12. }
  13. fastify.addSchema(sharedAddressSchema)
  14. const bodyJsonSchema = {
  15. type: 'object',
  16. properties: {
  17. vacation: 'sharedAddress#'
  18. }
  19. }
  20. const schema = { body: bodyJsonSchema }
  21. fastify.post('/the/url', { schema }, handler)

NB You can mix up the $ref-way and the replace-way when using fastify.addSchema.