Fast and Easy C++ Object Serializer

By Badger McFly

Using the Cheerio Library

In your class definition, create a serialization map as follows:

#include <Cheerio/AllSerializers.h>
class MyObject
{
   public:
      BEGIN_CHEERIO_MAP(MyObject)
         CHEERIO_ENTRY(m_nInt)
         CHEERIO_ENTRY(m_strWide)
         CHEERIO_ENTRY(m_map)
   END_CHEERIO_MAP();
   // You can also use CHEERIO_PARENT() to serialize base classes.

private:
   int m_nInt;
   std::basic_string<char> m_strWide;
   std::map<int, std::string> m_map;
};

In your header file, provide the functions to serialize/de-serialize the custom object:

CHEERIO_OBJECT_SERIALIZER(MyObject);

Then you're done :)

To serialize/de-serialize:

void TestSerialize()
{
   using namespace Cheerio::Cereal;

   std::string strBuff;
   {
      MyObject obj;
      Serialize(obj, strBuff);
   }
   {
      MyObject obj;
      DeSerialize(obj, strBuff);
   }
}

If you want to serialize many objects/native types, you can use the overloaded operators (<< and >>), as such:

void TestMany()
{
   using namespace std;
   using namespace Cheerio;
   using namespace Cereal;

   typedef vector<string> VectorStrings;
   typedef list<wstring>  ListWideStrings;
   string strBuff;

   // Serialize lots of stuff using operator overloads.
   // Catch exceptions thrown if the dynamic allocation fails.
   try
   {
      MyObject         obj;
      int              n666;
      string           is;
      ListWideStrings  theNumberOf;
      VectorStrings    theBeast;

      n666 = 666;
      is = " is ";
      theNumberOf.push_back(L" the ");
      theNumberOf.push_back(L" number ");
      theNumberOf.push_back(L" of ");
      theBeast.push_back(" the ");
      theBeast.push_back(" beast");
      HeapTargetBuffer buff(strBuff);
      buff << n666 << is << theNumberOf << theBeast;
      buff << obj;
   }
   catch (bad_alloc & e)   // std::string.resize()
   {
      cout << "Exception! " << e.what();
   }
   catch (Cereal::Exception & e)
   {
      cout << "Exception! " << e.what();
   }

   // Deserialize objects in the same order.
   // Ensure we catch cheeky exceptions for when the buffer
   // is too small for the object(s).
   try
   {
      MyObject         obj;
      int              n666;
      string           is;
      ListWideStrings  theNumberOf;
      VectorStrings    theBeast;

      SourceBuffer buff(strBuff);
      buff >> n666 >> is >> theNumberOf >> theBeast;
      buff >> obj;
   }
   catch (Cereal::Exception & e)
   {
      cout << "Exception! " << e.what();
   }
}

The buffers can be heap allocated or static. Versioning is also supported and the templates are extendable. See the source code for more complex examples.

This has been tested on VS2010 and VS2015 for 32-bit and 64-bit, but should work on any decent compiler that understands templates.

I originally wrote this to pass objects from Windows to Android over the network. As such, it converts from host types to network types when serializing and back again when de-serializing. This does mean that, for Windows, you will need to link to w32_2.lib, which provides the htons type functions.

If you are interested in how it works, there is a decent amount of comments in the source code, but I'd be happy to answer any questions or review suggestions for improvement.

One example I thought of is providing a plug-in means of adding any new serialization code, such as for XML. This just uses a binary format.

Enjoy.



Related Articles

Downloads

Comments

  • Version that can handle polymorphic reconstruction from stream

    Posted by Badger McFly on 10/01/2016 08:47am

    ...is not supported in this version but if anyone is interested please add a comment and I'll see about getting the article changed.

    Reply
  • Struct Example

    Posted by Seth on 09/24/2016 05:58am

    This is great work! Could you add a simple of example of serialising/deserialising a simple struct?

    • Struct serializing

      Posted by Badger McFly on 10/09/2016 07:32am

      Hi Seth, I think there was some issue with the comments on this page. I added some a few weeks ago and I've only just noticed they have appeared so sorry for the late reply. I think there should be an example of struct serializing in main.cpp/sampleobjects.cpp if memory serves. If not then let me know.

      Reply
    Reply
  • Authors note: This does not support polymorphic types (via shared_ptr and unique_ptr)

    Posted by Badger McFly on 09/23/2016 04:48am

    ...Though I have recently developed a version that does. If anyone is interested please add a comment and I'll see about an update to the article.

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date