title: Basic Serialization sidebar_position: 2 id: basic_serialization license: | Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
This page covers basic object graph serialization and the core serialization APIs.
Apache Fory™ provides automatic serialization of complex object graphs, preserving the structure and relationships between objects. The FORY_STRUCT macro generates efficient serialization code at compile time, eliminating runtime overhead.
Key capabilities:
std::optional<T>std::shared_ptr, std::unique_ptr)#include "fory/serialization/fory.h" #include <vector> #include <map> using namespace fory::serialization; // Define structs struct Address { std::string street; std::string city; std::string country; bool operator==(const Address &other) const { return street == other.street && city == other.city && country == other.country; } }; FORY_STRUCT(Address, street, city, country); struct Person { std::string name; int32_t age; Address address; std::vector<std::string> hobbies; std::map<std::string, std::string> metadata; bool operator==(const Person &other) const { return name == other.name && age == other.age && address == other.address && hobbies == other.hobbies && metadata == other.metadata; } }; FORY_STRUCT(Person, name, age, address, hobbies, metadata); int main() { auto fory = Fory::builder().xlang(true).build(); fory.register_struct<Address>(100); fory.register_struct<Person>(200); Person person{ "John Doe", 30, {"123 Main St", "New York", "USA"}, {"reading", "coding"}, {{"role", "developer"}} }; auto result = fory.serialize(person); auto decoded = fory.deserialize<Person>(result.value()); assert(person == decoded.value()); }
auto fory = Fory::builder().xlang(true).build(); fory.register_struct<MyStruct>(1); MyStruct obj{/* ... */}; // Serialize - returns Result<std::vector<uint8_t>, Error> auto result = fory.serialize(obj); if (result.ok()) { std::vector<uint8_t> bytes = std::move(result).value(); // Use bytes... } else { // Handle error std::cerr << result.error().to_string() << std::endl; }
// Serialize to existing Buffer (fastest path) Buffer buffer; auto result = fory.serialize_to(buffer, obj); if (result.ok()) { size_t bytes_written = result.value(); // buffer now contains serialized data } // Serialize to existing vector (zero-copy) std::vector<uint8_t> output; auto result = fory.serialize_to(output, obj); if (result.ok()) { size_t bytes_written = result.value(); // output now contains serialized data }
// Deserialize from raw pointer auto result = fory.deserialize<MyStruct>(data_ptr, data_size); if (result.ok()) { MyStruct obj = std::move(result).value(); } // Deserialize from vector std::vector<uint8_t> data = /* ... */; auto result = fory.deserialize<MyStruct>(data); // Deserialize from Buffer (updates reader_index) Buffer buffer(data); auto result = fory.deserialize<MyStruct>(buffer);
Fory uses a Result<T, Error> type for error handling:
auto result = fory.serialize(obj); // Check if operation succeeded if (result.ok()) { auto value = std::move(result).value(); // Use value... } else { Error error = result.error(); std::cerr << "Error: " << error.to_string() << std::endl; } // Or use FORY_TRY macro for early return FORY_TRY(bytes, fory.serialize(obj)); // Use bytes directly...
Common error types:
Error::type_mismatch - Type ID mismatch during deserializationError::invalid_data - Invalid or corrupted dataError::buffer_out_of_bound - Buffer overflow/underflowError::type_error - Type registration errorThe FORY_STRUCT macro registers a struct for serialization:
struct MyStruct { int32_t x; std::string y; std::vector<int32_t> z; }; // Must be in the same namespace as the struct FORY_STRUCT(MyStruct, x, y, z);
The macro:
Requirements:
Nested structs are fully supported:
struct Inner { int32_t value; }; FORY_STRUCT(Inner, value); struct Outer { Inner inner; std::string label; }; FORY_STRUCT(Outer, inner, label); // Both must be registered fory.register_struct<Inner>(1); fory.register_struct<Outer>(2);
serialize_to(buffer, obj) with pre-allocated buffersbuild() instead of build_thread_safe() when possibletrack_ref(false) when references aren't needed