Back to TILs

cereal - A C++11 library for serialization - 01

Date: 2020-12-19Last modified: 2022-12-13

cereal is a header-only C++11 serialization library. cereal takes arbitrary data types and reversibly turns them into different representations, such as compact binary encodings, XML, or JSON. cereal was designed to be fast, light-weight, and easy to extend - it has no external dependencies and can be easily bundled with other code or used standalone.

// Escolha um deles
#include <cereal/archives/binary.hpp>
#include <cereal/archives/json.hpp>
#include <cereal/archives/portable_binary.hpp>
#include <cereal/archives/xml.hpp>

#include <cereal/types/memory.hpp>
#include <cereal/types/unordered_map.hpp>
#include <fstream>
using namespace std;

struct MyRecord {
  uint8_t x, y;
  float   z;

  // Informar ao Cereal quais membros serializar
  template <class Archive>
  void serialize( Archive &ar )
  {
    ar( x, y, z );
  }
};
struct MyRecord2 {
  uint8_t x, y;
  float   z;

  // Informar ao Cereal quais membros serializar
  template <class Archive>
  void serialize( Archive &ar )
  {
    // veja a diferença no json/xml, agora os campos estão nomeados
    ar( CEREAL_NVP( x ), CEREAL_NVP( y ), CEREAL_NVP( z ) );
  }
};
struct SomeData {
  int32_t                                        id;
  shared_ptr<unordered_map<uint32_t, MyRecord>>  data;
  shared_ptr<unordered_map<uint32_t, MyRecord2>> data2;
  vector<int>                                    vec;

  template <class Archive>
  void save( Archive &ar ) const
  {
    ar( data, data2 );
  }

  template <class Archive>
  void load( Archive &ar )
  {
    static int32_t idGen = 0;
    id                   = idGen++;
    ar( data, data2 );
  }
};
int main()
{
  {
    ofstream osBin( "output/cereal_01.bin", ios::binary );
    ofstream osXml( "output/cereal_01.xml" );
    ofstream osJson( "output/cereal_01.json" );

    // Cria os arquivos de saída
    cereal::BinaryOutputArchive archiveBin( osBin );
    cereal::XMLOutputArchive    archiveXml( osXml );
    cereal::JSONOutputArchive   archiveJson( osJson );

    SomeData myData01;
    SomeData myData02;

    MyRecord rec;
    rec.x = 7;
    rec.y = 8;
    rec.z = 9;

    MyRecord2 rec2;
    rec.x = 72;
    rec.y = 82;
    rec.z = 92;

    myData01.data = make_shared<unordered_map<uint32_t, MyRecord>>();
    myData01.data->emplace( 1001, rec );
    myData01.data->emplace( 1002, rec );
    myData01.data->emplace( 1000, rec );

    myData01.data2 = make_shared<unordered_map<uint32_t, MyRecord2>>();
    myData01.data2->emplace( 1001, rec2 );
    myData01.data2->emplace( 1002, rec2 );
    myData01.data2->emplace( 1000, rec2 );

    int x = myData01.data->at( 1001 ).x;
    cout << "OUT data.x: " << x << endl;

    myData02.vec = { 10, 20, 30, 40 };

    archiveBin( myData01, myData02 );
    archiveXml( myData01, myData02 );
    archiveJson( myData01, myData02 );

    // RAII: Precisa sair do contexto para que os arquivos sejam escritos e fechados.
  }
  // Input
  {
    ifstream                isBin( "output/cereal_01.xml" );
    cereal::XMLInputArchive inArchiveBin( isBin );

    SomeData myData01B;
    SomeData myData02B;

    myData01B.data = make_shared<unordered_map<uint32_t, MyRecord>>();
    inArchiveBin( myData01B, myData02B );

    int x = myData01B.data->at( 1001 ).x;
    cout << "IN data.x: " << x << endl;
  }

  return 0;
}

Serialized files

XML

<?xml version="1.0" encoding="utf-8"?>
<cereal>
	<value0>
		<value0>
			<ptr_wrapper>
				<id>2147483649</id>
				<data size="dynamic">
					<value0>
						<key>1000</key>
						<value>
							<value0>72</value0>
							<value1>82</value1>
							<value2>92</value2>
						</value>
					</value0>
					<value1>
						<key>1002</key>
						<value>
							<value0>72</value0>
							<value1>82</value1>
							<value2>92</value2>
						</value>
					</value1>
					<value2>
						<key>1001</key>
						<value>
							<value0>72</value0>
							<value1>82</value1>
							<value2>92</value2>
						</value>
					</value2>
				</data>
			</ptr_wrapper>
		</value0>
		<value1>
			<ptr_wrapper>
				<id>2147483650</id>
				<data size="dynamic">
					<value0>
						<key>1000</key>
						<value>
							<x>0</x>
							<y>0</y>
							<z>0</z>
						</value>
					</value0>
					<value1>
						<key>1002</key>
						<value>
							<x>0</x>
							<y>0</y>
							<z>0</z>
						</value>
					</value1>
					<value2>
						<key>1001</key>
						<value>
							<x>0</x>
							<y>0</y>
							<z>0</z>
						</value>
					</value2>
				</data>
			</ptr_wrapper>
		</value1>
	</value0>
	<value1>
		<value0>
			<ptr_wrapper>
				<id>0</id>
			</ptr_wrapper>
		</value0>
		<value1>
			<ptr_wrapper>
				<id>0</id>
			</ptr_wrapper>
		</value1>
	</value1>
</cereal>


JSON

{
    "value0": {
        "value0": {
            "ptr_wrapper": {
                "id": 2147483649,
                "data": [
                    {
                        "key": 1000,
                        "value": {
                            "value0": 72,
                            "value1": 82,
                            "value2": 92.0
                        }
                    },
                    {
                        "key": 1002,
                        "value": {
                            "value0": 72,
                            "value1": 82,
                            "value2": 92.0
                        }
                    },
                    {
                        "key": 1001,
                        "value": {
                            "value0": 72,
                            "value1": 82,
                            "value2": 92.0
                        }
                    }
                ]
            }
        },
        "value1": {
            "ptr_wrapper": {
                "id": 2147483650,
                "data": [
                    {
                        "key": 1000,
                        "value": {
                            "x": 0,
                            "y": 0,
                            "z": 0.0
                        }
                    },
                    {
                        "key": 1002,
                        "value": {
                            "x": 0,
                            "y": 0,
                            "z": 0.0
                        }
                    },
                    {
                        "key": 1001,
                        "value": {
                            "x": 0,
                            "y": 0,
                            "z": 0.0
                        }
                    }
                ]
            }
        }
    },
    "value1": {
        "value0": {
            "ptr_wrapper": {
                "id": 0
            }
        },
        "value1": {
            "ptr_wrapper": {
                "id": 0
            }
        }
    }
}