Yes, use atdgen. It generates plain .mli
and .ml
files which are helpful to see what functions are available and how they are implemented should anything go wrong.
Another aspect of the design is that the ATD file can serve as strict documentation for your API. It is also possible to support code generation for other languages than OCaml. We have the equivalent of atdgen for Java (atdj) and it would be great to have some support for other languages as well.
For your example, you’d write a file statute.atd
like this:
type title = {
name: string;
number: int;
chapters: chapter list;
}
type chapter = string
Try the following and take look at the files that are generated:
$ atdgen -t statute.atd
$ atdgen -j -j-std statute.atd
$ atdgen -v statute.atd
(t = types, j = json, v = validators and record creators)
Also commonly used are optional fields with or without defaults:
type preferences = {
id: string; (* required field *)
?img_url: string option; (* defaults to None *)
~pets: pet list; (* defaults to the empty list *)
}
This allows missing or null json fields. The _v
generated module provides a function with the following signature:
val create_preferences : id:string -> ?img_url:string -> ?pets:pet list -> unit -> preferences
If you have abstract types, say a user ID that must follow a special syntax, you can use the wrap feature to get an OCaml type that maps to a basic type supported by json, like a string or an int. So instead of having type id = string
, you can use your special id
type:
type id = string wrap <ocaml module="ID">
where the ID
module that you provide contains the following:
type t (* type of a well-formed ID *)
val wrap : string -> t (* would raise an exception on malformed input *)
val unwrap : t -> string