title: Polymorphism and Dynamic Types 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
Fory Swift supports dynamic serialization for Any, AnyObject, arbitrary application protocol existentials, and supported heterogeneous collections. Any and AnyObject roots use direct convenience APIs. Application protocols and recursively composed carriers select DynamicSerializer explicitly.
let fory = Fory() let dynamic: Any = Int32(7) let data = try fory.serialize(dynamic) let decoded: Any = try fory.deserialize(data)
The equivalent explicit form is with: DynamicSerializer<Any>.self. It is useful when composing serializers, but is unnecessary for an Any root. AnyObject has the same direct root APIs.
A concrete external value passed as Any may use its registered serializer. For typed roots and fields, select a separate serializer explicitly with with:.
Heterogeneous containers compose carrier serializers:
typealias AnyArraySerializer = ArraySerializer<DynamicSerializer<Any>> typealias StringAnyMapSerializer = DictionarySerializer< String, DynamicSerializer<Any> >
Use DynamicSerializer<AnyHashable> for an erased dynamic dictionary key.
Use the exact heterogeneous shape for dynamic lists and maps: [Any], [String: Any], [Int32: Any], or [AnyHashable: Any]. For example, write ["a", "b"] as [Any] before storing that heterogeneous list in Any. Keep homogeneous lists and maps in their ordinary concrete types.
Register each concrete target that may appear. No Fory-specific marker protocol is required:
protocol Animal { var name: String { get } } @ForyStruct struct Dog: Animal { var name: String = "" } @ForyStruct(target: ThirdParty.Cat.self) struct CatSerializer { var name: String } let fory = Fory() try fory.register(Dog.self, id: 100) try fory.register(CatSerializer.self, id: 101) let input: any Animal = Dog(name: "Rex") let data = try fory.serialize( input, with: DynamicSerializer<any Animal>.self ) let output = try fory.deserialize( data, with: DynamicSerializer<any Animal>.self )
Every concrete target must conform to the requested application protocol. A target that is unregistered or does not conform fails deserialization.
Application protocol fields are dynamic:
@ForyStruct struct Zoo { var featured: any Animal var animals: [any Animal] }
Register Zoo and every concrete target that may appear.
Use an optional when the field needs a nil default:
@ForyStruct struct OptionalZoo { var featured: (any Animal)? = nil }
Use DynamicSerializer<T> as the child of a root carrier:
typealias AnimalArraySerializer = ArraySerializer<DynamicSerializer<any Animal>> let data = try fory.serialize( animals, with: AnimalArraySerializer.self ) let decoded = try fory.deserialize( data, with: AnimalArraySerializer.self )
Optional and map roots compose the same way:
typealias FeaturedSerializer = OptionalSerializer<DynamicSerializer<any Animal>> typealias AnimalMapSerializer = DictionarySerializer< String, DynamicSerializer<any Animal> >
Swift's normal Hashable rules still apply to set elements and dictionary keys. Use AnyHashable for erased dynamic keys.
Select DynamicSerializer<Base> when a class-typed field must preserve its concrete subclass:
@ForyField(with: DynamicSerializer<AnimalBase>.self) var animal: AnimalBase
Register every concrete subclass that may appear.
Any Fields@ForyStruct struct DynamicHolder { var value: Any = ForyAnyNullValue() var list: [Any] = [] var byName: [String: Any] = [:] var byId: [Int32: Any] = [:] var byDynamicKey: [AnyHashable: Any] = [:] }
If dynamic values contain user-defined types, register those concrete types.
@ForyStruct struct Address { var street: String = "" var zip: Int32 = 0 } let fory = Fory() try fory.register(Address.self, id: 100)
Any null representation: ForyAnyNullValueAnyObject null representation: NSNullAnyHashable dynamic null-key representation: AnyHashable(ForyAnyNullValue())AnyHashable KeysAnyHashable keys must wrap values that are both Hashable and supported by Fory dynamic serialization.