package conformist

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Module ConformistSource

Conformist is a library for creating and validating schemas. It provides run-time types without the use of ppx. It can be used to validate incoming data and to translate it to static types for safe usage.

Example

Let's start with an example. We have a static type that represents a user.

  type occupation =
    | Mathematician
    | Engineer

  type user =
    { occupation : occupation
    ; email : string
    ; birthday : Ptime.t
    ; nr_of_siblings : int
    ; comment : string option
    ; wants_premium : bool
    }

In order to create a conformist schema, we need a constructor that takes all the record fields and create a user.

  let user occupation email birthday nr_of_siblings comment wants_premium =
    { occupation; email; birthday; nr_of_siblings; comment; wants_premium }
  ;;

Now we can create a schema.

  let occupation_decoder = function
    | "mathematician" -> Ok Mathematician
    | "engineer" -> Ok Engineer
    | _ -> Error "Unknown occupation provided"
  ;;

  let occupation_encoder = function
    | Mathematician -> "mathematician"
    | Engineer -> "engineer"
  ;;

  let user_schema =
    Conformist.(
      make
        Field.
          [ custom
              occupation_decoder
              occupation_encoder
              "occupation"
              ~meta:()
          ; string "email"
          ; date "birthday"
          ; int ~default:0 "nr_of_siblings"
          ; optional (string "comment")
          ; bool "wants_premium"
          ]
        user)
  ;;

Try to delete/swap lines of that list, to change the constructor or the user type. The code doesn't compile anymore!

user_schema showcases the creation of a custom type and optional types.

This is how you can decode a user given some input:

  let user =
    let input =
      [ "occupation", [ "engineer" ]
      ; "email", [ "test@example.com" ]
      ; "birthday", [ "2020-12-01T00:00:00.00Z" ]
      ; "nr_of_siblings", [ "3" ]
      ; "comment", [ "hello" ]
      ; "wants_premium", [ "true" ]
      ]
    in
    Conformist.decode Schema.user_schema input
  ;;

Decoding doesn't validate the data, it just makes sure that the types are correct and translates strings to the correct static types.

We can validate data based on each field's validators.

  let validation_errors =
    let input =
      [ "occupation", [ "engineer" ]
      ; "email", [ "test@example.com" ]
      ; "birthday", [ "2020-12-01T00:00:00.00Z" ]
      ; "nr_of_siblings", [ "3" ]
      ; "comment", [ "hello" ]
      ; "wants_premium", [ "true" ]
      ]
    in
    Conformist.validate Schema.user_schema input
  ;;

Note that if decoding of a field fails, validation fails as well since before a field is validated it gets decoded.

Use decode_and_validate to do both steps.

Sourcetype error_msg = string

Fields

Every member of the list in the example is a field. Use the provided fold_left to traverse the list of fiels. Helper functions are provided that operate on fields.

Sourcemodule Field : sig ... end
Sourcetype 'a decoder = string list -> ('a, error_msg) result

A 'a decoder tries to turn values into a value of type 'a. It returns a descriptive errors message upon failure.

Sourcetype 'a encoder = 'a -> string list

A 'a encoder encodes a value of type 'a into a list of strings.

Sourcetype 'a validator = 'a -> error_msg option

A 'a validator takes something of type 'a and returns an error string if validation fails, None if everything is ok

Sourceval custom : 'a decoder -> 'a encoder -> ?default:'a -> ?type_:string -> ?meta:'b -> ?validator:'a validator -> string -> ('b, 'a) Field.t

Use custom decoder encoder ?default ?type_ ?meta ?validator field_name to create a field with a custom type that is not supported out-of-the box. Provide a custom decoder with a descriptive error message so conformist knows how to turn a string into your custom value.

A string representation of the static type_ can also be provided, by default the field_name is taken.

A default value can be provided.

Sourceval optional : ?meta:'a -> ('b, 'c) Field.t -> ('a, 'c option) Field.t

optional ?meta field turns a field into an optional field. If the field does not exist in the input data or if the associated value in the input data is an empty list, the value is None. If the data is not provided in the input at all, no validation logic is executed.

Example:

  let make name address = { name; address } in
  let schema =
    Conformist.(make [ string "name"; optional (string "address") ] make)
  in
  (* Decoding fails *)
  let decoded = Conformist.decode schema [] in
  (* Validation fails *)
  let validated = Conformist.validate [] in
  (* Decoding succeeds, address is [None] *)
  let decoded = Conformist.decode schema [ "name", [ "Walter" ] ] in
  let decoded =
    Conformist.decode schema [ "name", [ "Walter" ]; "address", [] ]
  in
  (* Validation succeeds *)
  let validated = Conformist.validate [ "name", [ "Walter" ] ] in
  ()
Sourceval list : ?default:'c list -> ?meta:'a -> ('b, 'c) Field.t -> ('a, 'c list) Field.t

list ?default ?meta field returns a field that decodes to a list of field.

default is an optional default value for the field.

meta is optional meta data that is attached to the field. This is useful when implementing features on top of conformist.

Sourceval bool : ?default:bool -> ?meta:'a -> ?msg:error_msg -> string -> ('a, bool) Field.t

bool ?default ?meta ?msg field_name returns a field with name field_name that decodes to a bool.

default is an optional default value for the field.

meta is optional meta data that is attached to the field. This is useful when implementing features on top of conformist.

msg is the decode error message that is returned if decode fails.

Sourceval float : ?default:float -> ?meta:'a -> ?msg:error_msg -> ?validator:float validator -> string -> ('a, float) Field.t

float ?default ?meta ?msg ?validator field_name returns a field with name field_name that decodes to float.

default is an optional default value for the field.

meta is optional meta data that is attached to the field. This is useful when implementing features on top of conformist.

msg is the decode error message that is returned if decode fails.

validator is an optional validator that is run when calling validate. By default, no validation logic is executed. This means that if a value decodes, it is valid.

Sourceval int : ?default:int -> ?meta:'a -> ?msg:error_msg -> ?validator:int validator -> string -> ('a, int) Field.t

int ?meta ?msg ?validator field_name returns a field with name field_name that decodes to int.

default is an optional default value for the field.

meta is optional meta data that is attached to the field. This is useful when implementing features on top of conformist.

msg is the decode error message that is returned if decode fails.

validator is an optional validator that is run when calling validate. By default, no validation logic is executed. This means that if a value decodes, it is valid.

Sourceval string : ?default:string -> ?meta:'a -> ?msg:error_msg -> ?validator:string validator -> string -> ('a, string) Field.t

string ?meta ?validator field_name return a field with name field_name that decodes to string.

default is an optional default value for the field.

meta is optional meta data that is attached to the field. This is useful when implementing features on top of conformist.

msg is the decode error message that is returned if decode fails.

validator is an optional validator that is run when calling validate. By default, no validation logic is executed. This means that if a value decodes, it is valid.

Sourceval date : ?default:Ptime.date -> ?meta:'a -> ?msg:error_msg -> ?validator:(int * int * int) validator -> string -> ('a, Ptime.date) Field.t

Don't use date, use datetime instead.

  • deprecated Use [Conformist.datetime] instead.
Sourceval datetime : ?default:Ptime.t -> ?meta:'a -> ?msg:error_msg -> ?validator:Ptime.t validator -> string -> ('a, Ptime.t) Field.t

datetime ?default ?meta ?validator field_name returns a field with name field_name that decodes to datetime.

default is an optional default value for the field.

meta is optional meta data that is attached to the field. This is useful when implementing features on top of conformist.

msg is the decode error message that is returned if decode fails.

validator is an optional validator that is run when calling validate. By default, no validation logic is executed. This means that if a value decodes, it is valid.

Schema

A schema is a list of fields. Input data can be decoded and validated using a schema.

Sourcetype ('meta, 'ctor, 'ty) t

t is a conformist schema.

Sourceval empty : ('a, unit, unit) t

empty creates an empty schema.

Sourceval make : ('a, 'b, 'c) Field.list -> 'b -> ('a, 'b, 'c) t

make fields constructor create a schema.

Sourceval fold_left : f:('res -> 'meta Field.any_field -> 'res) -> init:'res -> ('meta, 'args, 'ty) t -> 'res

fold_left ~f ~init schema traverses the list of fields of schema. Use the functions in Field to work with a generic field.

Sourcetype error = string * string list * error_msg

An error (field, value, error_message) is used to for decoding errors and validation errors.

field is the field name of the input that failed to decode or validate, values are the input values (if they were provided) and error_message is the decoding or validation error message.

An empty list of error means that the schema is valid.

Sourcetype input = (string * string list) list

The input represents unsafe data that needs to be decoded and validated. This is typically some user input.

Sourceval decode : ('meta, 'ctor, 'ty) t -> input -> ('ty, error) result

decode schema input returns the decoded value of type 'ty by decoding the input using the schema.

No validation logic is executed in this step.

Sourceval validate : ('meta, 'ctor, 'ty) t -> input -> error list

validate schema input returns a list of validation errors by running the validators defined in schema on the input data. An empty list implies that there are no validation errors and that the input is valid according to the schema.

Note that input that has no validation errors might still fail to decode, depending on the validation functions specified in schema.

Sourceval decode_and_validate : ('meta, 'ctor, 'ty) t -> input -> ('ty, error list) Result.t

decode_and_validate schema input returns the decoded and validated value of type 'ty by decoding the input using the schema and running its validators.

Use decode_and_validate to combine the functions decode and validate and to either end up with the decoded value or all errors that happened during the decoding and validation steps.

Sourcemodule Make (M : sig ... end) : sig ... end
OCaml

Innovation. Community. Security.