---
title: Polymorphic Serialization
sidebar_position: 9
id: polymorphism
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

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
---

Apache Fory™ supports polymorphic serialization through smart pointers (`std::shared_ptr` and `std::unique_ptr`), enabling dynamic dispatch and type flexibility for inheritance hierarchies.

## Supported Polymorphic Types

- `std::shared_ptr<Base>` - Shared ownership with polymorphic dispatch
- `std::unique_ptr<Base>` - Exclusive ownership with polymorphic dispatch
- Collections: `std::vector<std::shared_ptr<Base>>`, `std::map<K, std::unique_ptr<Base>>`
- Optional: `std::optional<std::shared_ptr<Base>>`

## Basic Polymorphic Serialization

```cpp
#include "fory/serialization/fory.h"

using namespace fory::serialization;

// Define base class with virtual methods
struct Animal {
  virtual ~Animal() = default;
  virtual std::string speak() const = 0;
  int32_t age = 0;
};
FORY_STRUCT(Animal, age);

// Define derived classes
struct Dog : Animal {
  std::string speak() const override { return "Woof!"; }
  std::string breed;
};
FORY_STRUCT(Dog, FORY_BASE(Animal), breed);

struct Cat : Animal {
  std::string speak() const override { return "Meow!"; }
  std::string color;
};
FORY_STRUCT(Cat, FORY_BASE(Animal), color);

// Struct with polymorphic field
struct Zoo {
  std::shared_ptr<Animal> star_animal;
};
FORY_STRUCT(Zoo, star_animal);

int main() {
  auto fory = Fory::builder().xlang(true).track_ref(true).build();

  // Register all types with unique type IDs
  fory.register_struct<Zoo>(100);
  fory.register_struct<Dog>(101);
  fory.register_struct<Cat>(102);

  // Create object with polymorphic field
  Zoo zoo;
  zoo.star_animal = std::make_shared<Dog>();
  zoo.star_animal->age = 3;
  static_cast<Dog*>(zoo.star_animal.get())->breed = "Labrador";

  // Serialize
  auto bytes_result = fory.serialize(zoo);
  assert(bytes_result.ok());

  // Deserialize - concrete type is preserved
  auto decoded_result = fory.deserialize<Zoo>(bytes_result.value());
  assert(decoded_result.ok());

  auto decoded = std::move(decoded_result).value();
  assert(decoded.star_animal->speak() == "Woof!");
  assert(decoded.star_animal->age == 3);

  auto* dog_ptr = dynamic_cast<Dog*>(decoded.star_animal.get());
  if (dog_ptr == nullptr || dog_ptr->breed != "Labrador") {
    return 1;
  }
}
```

## Type Registration for Polymorphism

For polymorphic serialization, register derived types with unique type IDs:

```cpp
// Register with numeric type ID
fory.register_struct<Derived1>(100);
fory.register_struct<Derived2>(101);
```

**Why type ID registration?**

- Compact binary representation
- Fast type lookup and dispatch
- Consistent with non-polymorphic type registration

## Automatic Polymorphism Detection

Fory automatically detects polymorphic types using `std::is_polymorphic<T>`:

```cpp
struct Base {
  virtual ~Base() = default;  // Virtual destructor makes it polymorphic
  int32_t value = 0;
};

struct NonPolymorphic {
  int32_t value = 0;  // No virtual methods
};

// Polymorphic field - type info written automatically
struct Container1 {
  std::shared_ptr<Base> ptr;  // Auto-detected as polymorphic
};

// Non-polymorphic field - no type info written
struct Container2 {
  std::shared_ptr<NonPolymorphic> ptr;  // Not polymorphic
};
```

## Controlling Dynamic Dispatch

Use `fory::F().dynamic(V)` in `FORY_STRUCT` to override automatic
polymorphism detection:

```cpp
struct Animal {
  virtual ~Animal() = default;
  virtual std::string speak() const = 0;
};

struct Pet {
  // Auto-detected: type info written (Animal has virtual methods)
  std::shared_ptr<Animal> animal1;

  // Force dynamic: type info written explicitly
  std::shared_ptr<Animal> animal2;

  // Force non-dynamic: skip type info (faster but no subtype support)
  std::shared_ptr<Animal> animal3;
};
FORY_STRUCT(Pet, animal1, (animal2, fory::F().dynamic(true)),
            (animal3, fory::F().dynamic(false)));
```

**When to use `dynamic(false)`:**

- You know the concrete type will always match the declared type
- Performance is critical and you don't need subtype support
- Working with monomorphic data despite having a polymorphic base class

### Schema Metadata

Configure field metadata directly in `FORY_STRUCT`:

```cpp
struct Zoo {
  std::shared_ptr<Animal> star;      // Auto-detected as polymorphic
  std::shared_ptr<Animal> backup;    // Nullable polymorphic field
  std::shared_ptr<Animal> mascot;    // Non-dynamic (no subtype dispatch)
};
FORY_STRUCT(Zoo, (star, fory::F(0)),
            (backup, fory::F(1).nullable()),
            (mascot, fory::F(2).dynamic(false)));
```

See [Schema Metadata](schema-metadata.md) for complete details on
`nullable()`, `ref()`, and other field-level options.

## std::unique_ptr Polymorphism

`std::unique_ptr` works the same way as `std::shared_ptr` for polymorphic types:

```cpp
struct Container {
  std::unique_ptr<Animal> pet;
};
FORY_STRUCT(Container, pet);

auto fory = Fory::builder().xlang(true).track_ref(true).build();
fory.register_struct<Container>(200);
fory.register_struct<Dog>(201);

Container container;
container.pet = std::make_unique<Dog>();
static_cast<Dog*>(container.pet.get())->breed = "Beagle";

auto bytes = fory.serialize(container).value();
auto decoded = fory.deserialize<Container>(bytes).value();

// Dynamic type preserved
auto* dog = dynamic_cast<Dog*>(decoded.pet.get());
assert(dog != nullptr);
assert(dog->breed == "Beagle");
```

## Collections of Polymorphic Objects

```cpp
#include <vector>
#include <map>

struct AnimalShelter {
  std::vector<std::shared_ptr<Animal>> animals;
  std::map<std::string, std::unique_ptr<Animal>> registry;
};
FORY_STRUCT(AnimalShelter, animals, registry);

auto fory = Fory::builder().xlang(true).track_ref(true).build();
fory.register_struct<AnimalShelter>(100);
fory.register_struct<Dog>(101);
fory.register_struct<Cat>(102);

AnimalShelter shelter;
shelter.animals.push_back(std::make_shared<Dog>());
shelter.animals.push_back(std::make_shared<Cat>());
shelter.registry["pet1"] = std::make_unique<Dog>();

auto bytes = fory.serialize(shelter).value();
auto decoded = fory.deserialize<AnimalShelter>(bytes).value();

// All concrete types preserved
assert(dynamic_cast<Dog*>(decoded.animals[0].get()) != nullptr);
assert(dynamic_cast<Cat*>(decoded.animals[1].get()) != nullptr);
assert(dynamic_cast<Dog*>(decoded.registry["pet1"].get()) != nullptr);
```

## Reference Tracking

Reference tracking for `std::shared_ptr` works the same with polymorphic types.
See [Supported Types](supported-types.md) for details and examples.

## Nested Polymorphism Depth Limit

To prevent stack overflow from deeply nested polymorphic structures, Fory limits the maximum dynamic nesting depth:

```cpp
struct Container {
  virtual ~Container() = default;
  int32_t value = 0;
  std::shared_ptr<Container> nested;
};
FORY_STRUCT(Container, value, nested);

// Default max_dyn_depth is 5
auto fory1 = Fory::builder().xlang(true).build();
assert(fory1.config().max_dyn_depth == 5);

// Increase limit for deeper nesting
auto fory2 = Fory::builder().xlang(true).max_dyn_depth(10).build();
fory2.register_struct<Container>(1);

// Create deeply nested structure
auto level3 = std::make_shared<Container>();
level3->value = 3;

auto level2 = std::make_shared<Container>();
level2->value = 2;
level2->nested = level3;

auto level1 = std::make_shared<Container>();
level1->value = 1;
level1->nested = level2;

// Serialization succeeds
auto bytes = fory2.serialize(level1).value();

// Deserialization succeeds with sufficient depth
auto decoded = fory2.deserialize<std::shared_ptr<Container>>(bytes).value();
```

**Depth exceeded error:**

```cpp
auto fory_shallow = Fory::builder().xlang(true).max_dyn_depth(2).build();
fory_shallow.register_struct<Container>(1);

// 3 levels exceeds max_dyn_depth=2
auto result = fory_shallow.deserialize<std::shared_ptr<Container>>(bytes);
assert(!result.ok());  // Fails with depth exceeded error
```

**When to adjust:**

- **Increase `max_dyn_depth`**: For legitimate deeply nested polymorphic data structures
- **Decrease `max_dyn_depth`**: For stricter security requirements or shallow data structures

## Nullability for Polymorphic Fields

By default, `std::shared_ptr<T>` and `std::unique_ptr<T>` fields are treated as
non-nullable in the schema. To allow `nullptr`, mark the field nullable in
`FORY_STRUCT`.

```cpp
struct Pet {
  // Non-nullable (default)
  std::shared_ptr<Animal> primary;

  // Nullable via explicit field metadata
  std::shared_ptr<Animal> optional;
};
FORY_STRUCT(Pet, primary, (optional, fory::F().nullable()));
```

See [Schema Metadata](schema-metadata.md) for more details.

## Combining Polymorphism with Other Features

### Polymorphism + Reference Tracking

```cpp
struct GraphNode {
  virtual ~GraphNode() = default;
  int32_t id = 0;
  std::vector<std::shared_ptr<GraphNode>> neighbors;
};
FORY_STRUCT(GraphNode, id, neighbors);

struct WeightedNode : GraphNode {
  double weight = 0.0;
};
FORY_STRUCT(WeightedNode, FORY_BASE(GraphNode), weight);

// Enable ref tracking to handle shared references and cycles
auto fory = Fory::builder().xlang(true).track_ref(true).build();
fory.register_struct<GraphNode>(100);
fory.register_struct<WeightedNode>(101);

// Create cyclic graph
auto node1 = std::make_shared<WeightedNode>();
node1->id = 1;

auto node2 = std::make_shared<WeightedNode>();
node2->id = 2;

node1->neighbors.push_back(node2);
node2->neighbors.push_back(node1);  // Cycle

auto bytes = fory.serialize(node1).value();
auto decoded = fory.deserialize<std::shared_ptr<GraphNode>>(bytes).value();
// Cycle handled correctly
```

### Polymorphism + Schema Evolution

Compatible mode is enabled by default for schema evolution with polymorphic types:

```cpp
auto fory = Fory::builder()
    .xlang(true)
    .track_ref(true)
    .build();
```

## Best Practices

1. **Use type ID registration** for polymorphic types:

   ```cpp
   fory.register_struct<DerivedType>(100);
   ```

2. **Enable reference tracking** for polymorphic types:

   ```cpp
   auto fory = Fory::builder().xlang(true).track_ref(true).build();
   ```

3. **Virtual destructors required**: Ensure base classes have virtual destructors:

   ```cpp
   struct Base {
     virtual ~Base() = default;  // Required for polymorphism
   };
   ```

4. **Declare every serialized base relationship** with `FORY_BASE`:

   ```cpp
   FORY_STRUCT(DerivedType, FORY_BASE(BaseType), derived_field);
   ```

   This lets Fory validate polymorphic values and correctly adjust pointers for
   multiple inheritance during deserialization. A derived value whose base
   relationship is not declared cannot be deserialized through that base smart
   pointer type.

5. **Register all concrete types** before serialization/deserialization:

   ```cpp
   fory.register_struct<Derived1>(100);
   fory.register_struct<Derived2>(101);
   ```

6. **Use `dynamic_cast`** to downcast after deserialization:

   ```cpp
   auto* derived = dynamic_cast<DerivedType*>(base_ptr.get());
   if (derived) {
     // Use derived-specific members
   }
   ```

7. **Adjust `max_dyn_depth`** based on your data structure depth:

   ```cpp
   auto fory = Fory::builder().xlang(true).max_dyn_depth(10).build();
   ```

8. **Use `nullable()`** for optional polymorphic fields:

   ```cpp
   FORY_STRUCT(Holder, (optional_ptr, fory::F().nullable()));
   ```

## Error Handling

```cpp
auto bytes_result = fory.serialize(obj);
if (!bytes_result.ok()) {
  std::cerr << "Serialization failed: "
            << bytes_result.error().to_string() << std::endl;
  return;
}

auto decoded_result = fory.deserialize<MyType>(bytes_result.value());
if (!decoded_result.ok()) {
  std::cerr << "Deserialization failed: "
            << decoded_result.error().to_string() << std::endl;
  return;
}
```

**Common errors:**

- **Type not registered**: Register all concrete types with unique IDs before use
- **Depth exceeded**: Increase `max_dyn_depth` for deeply nested structures
- **Type ID conflict**: Ensure each type has a unique type ID across all registered types

## Performance Considerations

**Polymorphic serialization overhead:**

- Type metadata written for each polymorphic object (~16-32 bytes)
- Dynamic type resolution during deserialization
- Virtual function calls for dynamic dispatch

**Optimization tips:**

1. **Use `dynamic(false)`** when the concrete type matches the declared type:

   ```cpp
   FORY_STRUCT(Holder, (fixed_type, fory::F().dynamic(false)));
   ```

2. **Minimize nesting depth** to reduce metadata overhead

3. **Batch polymorphic objects** in collections rather than individual fields

4. **Consider non-polymorphic alternatives** when polymorphism isn't needed:

   ```cpp
   std::variant<Dog, Cat> animal;  // Type-safe union instead of polymorphism
   ```

## Related Topics

- [Type Registration](type-registration.md) - Registering types for serialization
- [Schema Metadata](schema-metadata.md) - Field-level metadata and options
- [Supported Types](supported-types.md) - Smart pointers and collections
- [Configuration](configuration.md) - `max_dyn_depth` and other settings
- [Basic Serialization](basic-serialization.md) - Core serialization concepts
