# USCiLab/cereal: A Header-Only C++11 Serialization Library

> cereal turns C++ types into binary, XML or JSON without external dependencies. It suits projects that already own their type definitions and want archive formats they can swap at compile time.

**USCiLab/cereal** — A C++11 library for serialization

- Repository: https://github.com/USCiLab/cereal
- Stars: 4,708 · Forks: 843
- Language: C++
- License: BSD-3-Clause
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/uscilab-cereal

## What cereal solves for C++ projects that own their types

Serialization in C++ usually means either writing per-type read and write functions by hand or pulling in a framework that dictates how your classes look. cereal sits in between. It is a header-only C++11 library that turns arbitrary data types into binary, XML or JSON representations and back, and the README states it has no external dependencies, so it can be bundled with other code or used standalone. The audience is narrow and specific: teams that already control their struct and class definitions and want to add save and load behaviour without introducing a build dependency or a code generator. The README points readers to the project web page for full installation and usage documentation, which means the repository itself is not the primary reference. That is worth knowing before you start: the README is a quick tour, not a manual.

## How the serialize function and archive classes fit together

The mechanism is a member function template. A type exposes either a single serialize() method or a save() and load() pair, each taking an Archive reference, and inside it calls ar() on the members it wants written. The archive type decides the format. The README example includes cereal/archives/binary.hpp and constructs a cereal::BinaryOutputArchive over a std::ofstream opened with std::ios::binary, then calls archive(myData). The same serialize function works with other archive headers because the member function is a template over the archive type. cereal also ships built-in support for standard library types through headers such as cereal/types/unordered_map.hpp and cereal/types/memory.hpp, which is how the README example serializes a std::shared_ptr holding a std::unordered_map. Note the asymmetry in the example: SomeData defines save() and load() separately rather than serialize(), and load() assigns an id from a static counter instead of reading it from the archive. That is a deliberate demonstration that the two directions need not be symmetric, and it is also a trap for anyone who assumes round-tripping is automatic.

## Installing cereal and saving your first record

There is no package manager step in the README. The instructions are to download cereal and place the headers somewhere your code can see them. The repository layout confirms this: the headers live under include/, and there is a CMakeLists.txt plus a Config.cmake.in at the top level for projects that want to consume it through CMake. The README's own example is the first real use. It defines MyRecord with three fields and a serialize() template, defines SomeData with a save() and load() pair, and writes to a file named out.cereal.

```cpp
#include <cereal/types/unordered_map.hpp>
#include <cereal/types/memory.hpp>
#include <cereal/archives/binary.hpp>
#include <fstream>

struct MyRecord
{
  uint8_t x, y;
  float z;

  template <class Archive>
  void serialize( Archive & ar )
  {
    ar( x, y, z );
  }
};
```

Running the resulting binary produces out.cereal in the working directory. The file is binary, so opening it in a text editor shows nothing useful; to inspect the contents you would swap the binary archive header for an XML or JSON archive header and rebuild. The README does not show that swap, but the archive-per-format structure implies it, and the project documentation is where the archive list is maintained.

## Where cereal is the wrong tool

cereal assumes both sides of the conversation share the same type definitions. If you need a stable wire format that older readers can parse after a producer changes its struct, the README offers nothing. There is no schema file, no field numbering, and no documented compatibility policy for changing a type between releases. The version tags that exist in the repository (v1.3.0, v1.3.1, v1.3.2) are library releases, not data format versions, and the documentation does not describe a migration path for data written by an older library version. A second limitation is the save/load asymmetry shown in the README example: nothing stops you from writing a load() that ignores archived fields, and nothing warns you when you do. Round-trip integrity is your responsibility, not the library's. Finally, if your data model is driven by an external schema or an IDL, a code-generation approach fits better than hand-written serialize() functions, because cereal has no generator.

## cereal compared with a schema-first serializer

The closest alternative in the C++ space is a schema-first serializer such as Google Protocol Buffers, where you write a .proto file and generate C++ classes from it. The difference in approach is where the type definition lives. With cereal, your existing C++ struct is the schema, and you add a serialize() template to it; there is no separate definition file and no build step that regenerates code. With Protocol Buffers, the .proto file is the source of truth, field numbers are explicit, and the generated code handles forward and backward compatibility. That buys you evolution guarantees cereal does not claim to provide, at the cost of a code generator in your build and a mapping layer between generated types and your own. If your types are already stable and internal, cereal's approach removes a build dependency. If they change often and other systems read the output, the schema-first route is the one with a documented answer to that problem.

## Maintenance, releases and the BSD-3-Clause licence

The repository is not archived, and the last push was on 2026-03-11, roughly six months before the date of this writing. The most recent tagged release is v1.3.2 from 2022-02-28, preceded by v1.3.1 in January 2022 and v1.3.0 in 2019. So commits continue while tags are sparse. The practical upgrade cost is low for a header-only library: you replace the headers and rebuild. The risk sits in the data, not the build. If a type's serialize() function changes shape between the version that wrote a file and the version that reads it, the documentation does not describe a compatibility guarantee, so any stored archives should be treated as tied to the code that produced them. The licence is BSD-3-Clause. That is a permissive licence, and the README states it plainly. It permits use in closed-source products subject to the licence's conditions, which typically include retaining the copyright notice and disclaimer. Read the LICENSE file in the repository for the exact terms; this is a description of the licence, not legal advice.

## Conclusion

Adopt cereal if your project defines its own types and you want binary, XML or JSON archives behind one serialize() function, with no dependency beyond headers. Do not adopt it if you need cross-version wire compatibility guarantees or schema evolution tooling, because the documentation does not describe a migration mechanism for changing type layouts. Before committing, verify which archive format your data actually needs and check that the version tags in your saved data match the library version you compile against, since the README does not document rollback or downgrade behaviour.

## FAQ

### Is cereal a header-only library, and does it need external dependencies?

Yes. The README describes cereal as a header-only C++11 serialization library with no external dependencies, which means it can be bundled with other code or used standalone. Installation consists of placing the headers somewhere your compiler can see them.

### Which archive formats does cereal support?

The README names compact binary encodings, XML and JSON as the representations cereal can produce. The example uses cereal/archives/binary.hpp with a cereal::BinaryOutputArchive; the archive header you include selects the format.

### What licence does cereal use?

cereal is licensed under BSD-3-Clause, and the README links to the BSD license text. The LICENSE file in the repository holds the exact terms.

## Sources

- [Issues](https://github.com/USCiLab/cereal/issues)
- [License: BSD-3-Clause](https://github.com/USCiLab/cereal/blob/master/LICENSE)
- [README](https://github.com/USCiLab/cereal/blob/master/README.md)
- [Releases](https://github.com/USCiLab/cereal/releases)
- [USCiLab/cereal on GitHub](https://github.com/USCiLab/cereal)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/uscilab-cereal
