| Home | API Documentation |
Internal: Mug · ThorsMug · ThorsSlack · NisseServer · NisseHTTP · ThorsSocket · ThorsCrypto · ThorsSerializer · ThorsMongo · ThorsLogging · ThorsIOUtil
Detailed architecture, traits system, and implementation details for the ThorsSerializer library.
Source: third/ThorsSerializer/src/Serialize/
ThorsSerializer is built on a traits-based system with four layers:
Traits<T> – A template specialization that describes the shape of type T (which members to read/write). Generated by macros.jsonExporter() etc. Integrate with operator<< / operator>>.Traits<T> metadata and drives the printer/parser.All serialization metadata is resolved at compile time.
| File | Purpose |
|---|---|
Traits.h |
Core Traits<T> class and all declaration macros |
SerUtil.h |
Traits<T> specializations for standard containers |
Serialize.h / Serialize.tpp |
Serializer and DeSerializer engines |
Exporter.h |
Exporter wrapper with operator<< |
Importer.h |
Importer wrapper with operator>> |
PrinterInterface.h/.cpp |
Abstract printer base class |
ParserInterface.h/.cpp |
Abstract parser base class |
JsonParser.h/.cpp |
JSON parser implementation |
JsonPrinter.cpp |
JSON printer implementation |
JsonThor.h |
JSON exporter/importer factory functions |
YamlParser.h/.cpp |
YAML parser (wraps libyaml) |
YamlPrinter.h/.cpp |
YAML printer (wraps libyaml) |
YamlThor.h |
YAML exporter/importer factory functions |
BsonParser.h/.cpp |
BSON parser |
BsonPrinter.h/.cpp |
BSON printer |
BsonThor.h |
BSON exporter/importer factory functions |
BsonConfig.h/.cpp |
BSON-specific configuration |
PrinterConfig.h |
PrinterConfig class |
ParserConfig.h |
ParserConfig class |
CustomSerialization.h/.tpp |
DefaultCustomSerializer<T> base class |
StringInput.h |
String-to-stream adapter for deserialization |
StringOutput.h |
Stream-to-string adapter for serialization |
UnicodeIterator.h |
Unicode handling for JSON strings |
Format.h |
Format detection utilities |
PolymorphicMarker.h |
Polymorphic type registration |
MongoUtility.h/.cpp |
MongoDB ObjectId support |
| Value | Meaning |
|---|---|
Invalid |
No traits defined (compile error if serialized) |
Map |
Object with named fields (structs/classes) |
Array |
Ordered sequence (vectors, lists) |
Parent |
Object that extends a serializable parent |
Value |
Primitive value (int, string, bool) |
Enum |
Enumeration type |
Pointer |
Pointer/smart pointer |
Reference |
Reference wrapper, optional |
Custom_Serialize |
Custom serialization handler |
Variant |
std::variant |
For a Map type:
template<>
struct Traits<MyType> {
static constexpr TraitType type = TraitType::Map;
using Members = std::tuple<
std::pair<char const*, int MyType::*>,
std::pair<char const*, std::string MyType::*>
>;
static Members const& getMembers();
};
The getMembers() function returns a tuple of (name, member-pointer) pairs.
ThorsAnvil_MakeTrait(Color, red, green, blue) expands to a Traits<Color> specialization in the ThorsAnvil::Serialize namespace with:
type = TraitType::Map{&"red", &Color::red}, {&"green", &Color::green}, {&"blue", &Color::blue}ThorsAnvil_ExpandTrait(Base, Derived, field) adds:
using Parent = Basetype = TraitType::ParentSerializer::print(object) dispatches based on Traits<T>::type:
Map/Parent: calls printer.openMap(), iterates members via printObjectMembers(), calls printer.closeMap()Array: calls printer.openArray(), iterates elements, calls printer.closeArray()Value: calls printer.addValue(object)Pointer: dereferences and serializes the pointed-to valueCustom_Serialize: delegates to the registered custom serializerprintObjectMembers() uses std::apply to iterate the members tuple, calling printer.addKey(name) then recursively serializing each member.Parent types, it first serializes the parent’s members, then the derived class’s members.DeSerializer::parse(object) dispatches based on Traits<T>::type:
Map/Parent: calls parser.getNextToken() expecting MapStart, then loops reading key-value pairsArray: calls parser.getNextToken() expecting ArrayStart, then loops reading elementsValue: calls parser.getValue(object)ParseType (ignored, warned, or thrown).Exact parsing additionally checks that all declared members were seen.class PrinterInterface {
public:
virtual void openDoc() = 0;
virtual void closeDoc() = 0;
virtual void openMap(std::size_t size) = 0;
virtual void closeMap() = 0;
virtual void openArray(std::size_t size) = 0;
virtual void closeArray() = 0;
virtual void addKey(std::string_view key) = 0;
virtual void addValue(short/int/long/double/bool/string...) = 0;
virtual void addNull() = 0;
};
class ParserInterface {
public:
virtual ParserToken getNextToken() = 0;
virtual std::string getKey() = 0;
virtual void getValue(short&/int&/long&/double&/bool&/string&...) = 0;
virtual bool isValueNull() = 0;
};
enum class ParserToken { DocStart, DocEnd, MapStart, MapEnd, ArrayStart, ArrayEnd, Key, Value, Error };
Allows operator>> from std::string and std::string_view. Creates a temporary std::istringstream from the string data.
Allows operator<< to std::string. Creates a temporary std::ostringstream and appends the result to the target string.
ThorsAnvil_PolyMorphicSerializer(Type) adds a virtual method to the class that returns the type name. The ThorsAnvil_RegisterPolyMorphicType macro registers the type in a global map.
When serializing a pointer to a base class, the serializer:
"__type": "ConcreteType" as the first key-value pair.When deserializing:
"__type" key.When serializing std::shared_ptr<T>:
{"__id": N, ...data...}.{"__ref": N}.On deserialization, the IDs are used to reconstruct shared ownership.
BSON requires knowing the byte size of an object before writing it (the size is part of the header). The bsonGetPrintSize() function pre-computes this by walking the traits metadata and summing field sizes.
Custom serializers must implement getPrintSizeBson() for BSON support.
ThorsAnvil_MakeTrait macros must be at global scope (they generate specializations in the ThorsAnvil::Serialize namespace).ThorsAnvil_MakeTrait() call (limited by macro expansion depth).ParseType::Weak)./Zc:preprocessor for conforming variadic macro support.