package serde

  1. Overview
  2. Docs
A serialization framework for OCaml


Dune Dependency






Serde is a serialization framework for OCaml that runs on the principle of maximum efficiency and user ergonomics while maintaining format flexibility. Internally Serde uses an intermediate language that can be cheaply mapped to and from different target formats like JSON, XML, or S-expressions, which makes Serde good for transcoding data as well.

Published: 25 Aug 2023


A serialization framework for OCaml inspired by serde-rs.

The main goals for are:

  • Serialization -- take arbitary data structures from the user and turn them into specific formats with maximum efficiency.

  • Deserialization -- read arbitrary data that you parse into data structures of the user's choice with maximum efficiency.

type rank = Captain | Chief_petty_officer [@@deriving serializer, deserializer]
type t = { name : string; rank : rank } [@@deriving serializer, deserializer]

let obrien = { name = "Miles O'Brien"; rank = Chief_petty_officer }
let sisko = { name = "Benjamin Sisko"; rank = Captain }

> Serde_json.to_string_pretty (serialize_t) obrien
Ok "{ \"name\": \"Miles O'Brien\", \"rank\": \"Chief_petty_officer\" }"

> Serde_json.of_string (deserialize_t) "{ \"name\": \"Miles O'Brien\", \"rank\": \"Chief_petty_officer\" }"
Ok {name = "Miles O'Brien"; rank = Chief_petty_officer}

> Serde_sexpr.to_string_pretty (serialize_t) obrien;;
Ok "(\"Miles O'Brien\" :Chief_petty_officer)"

> Serde_sexpr.of_string (deserialize_t) "(\"Miles O'Brien\" :Chief_petty_officer)";;
Ok {name = "Miles O'Brien"; rank = Chief_petty_officer}


Set up the serde_derive ppx, and bring in any data format modules you want to use. Here we bring s-expressions and json.

 (name my_lib)
 (preprocess (pps serde_derive))
 (libraries serde serde_derive serde_sexpr serde_json))

Tag your data structures with deriving (serializer, deserializer).

open Serde

type t =
  | Hello
  | Tuple1 of string
  | Tuple2 of string * bool
  | Record3 of { name : string; favorite_number : int; location : string }
[@@deriving (serializer, deserializer)]

Now you have a serialize_{typeName} and deserialize_{typeName} functions that you can pass into the different data format modules.

To read data, use deserialize_t like this:

let sexpr = "(:Record3 (\"Benjamin Sisko\" 9 \"Bajor\"))" in
let* t = Serde_sexpr.of_string deserialize_t sexpr in
t = (Record3 { name = "Benjamin Sisko"; favorite_number = 9; location = "Bajor" })

To render data, use serialize_t like this:

let t = (Record3 { name = "Benjamin Sisko"; favorite_number = 9; location = "Bajor" }) in
let* sexpr = Serde_sexpr.to_string_pretty serialize_t t in
sexpr = "(:Record3 (\"Benjamin Sisko\" 9 \"Bajor\"))"

To transcode data across formats, switch the data module:

(* read sexpr *)
let sexpr = "(:Record3 (\"Benjamin Sisko\" 9 \"Bajor\"))" in
let* t = Serde_sexpr.of_string deserialize_t sexpr in
(* write json *)
let* json = Serde_json.to_string_pretty serialize_t t in
json = "{
  \"t#Record3\": {
    \"name\": \"Benjamin Sisko\",
    \"favorite_number\": 9,
    \"location\": \"Deep Space 9\"


Check the for a small guide on how to implement new data formats.

Advanced Use: Custom Serializer/Deserializer is capable of deriving the right serializer/deserializer for your types (and it if doesn't, that's a bug!) but in some cases you want to fit some external data format into an existing internal representation without having to add an extra layer.

In those cases, you can implement a Serde Visitor and customize absolutely everything about it. You can get started by using serde_derive and dune describe pp to expand the derivation. This will give you a solid starting point for your data type, where you can see how the generated Visitor drives the Deserializer by asking it to deserialize specific datatypes.

Dependencies (3)

  1. ppx_inline_test >= "v0.16.0"
  2. ocaml >= "4.14.0"
  3. dune >= "3.5"

Dev Dependencies (1)

  1. odoc with-doc