{"id":21177562,"url":"https://github.com/sachskaylee/baseserializer","last_synced_at":"2026-05-22T07:02:05.214Z","repository":{"id":129373557,"uuid":"163560690","full_name":"SachsKaylee/BaseSerializer","owner":"SachsKaylee","description":"An extensible serializer for .NET Standard. Capable of cyclic references. 👜","archived":false,"fork":false,"pushed_at":"2018-12-31T00:56:12.000Z","size":40,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-21T11:44:49.249Z","etag":null,"topics":["csharp","reference","serializer","unity","xml"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SachsKaylee.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-12-30T04:11:54.000Z","updated_at":"2019-02-09T20:19:58.000Z","dependencies_parsed_at":"2023-07-29T02:05:10.804Z","dependency_job_id":null,"html_url":"https://github.com/SachsKaylee/BaseSerializer","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SachsKaylee%2FBaseSerializer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SachsKaylee%2FBaseSerializer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SachsKaylee%2FBaseSerializer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SachsKaylee%2FBaseSerializer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SachsKaylee","download_url":"https://codeload.github.com/SachsKaylee/BaseSerializer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243624848,"owners_count":20321179,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csharp","reference","serializer","unity","xml"],"created_at":"2024-11-20T17:16:26.733Z","updated_at":"2026-05-22T07:02:00.185Z","avatar_url":"https://github.com/SachsKaylee.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# BaseSerializer\n\n## What is this?\n\nBaseSerializer is an XML based serializer capable of complex(e.g. cyclic) data structures. This is achieved by internally treating everything a reference and splitting object creation into two steps: Creation and actual deserilization.\n\n## How to use?\n\nInstall this library like you would any other. This library has a simple public API.\n\n### Serialization\n\n```csharp\nBaseSerializer serializer = new BaseSerializer();\nXDocument xmlDocument = serializer.Serialize(myObject);\n```\n\nYou can then manually transform this document or save it to the disc. ([XDocument documentation](https://docs.microsoft.com/en-us/dotnet/api/system.xml.linq.xdocument?view=netcore-2.1))\n\n```csharp\nxmlDocument.Save(\"~/Documents/Data.xml\");\n```\n\n### Deserialization\n\nA XDocument reference can be deserialized to an object.\n\n```csharp\nxmlDocument = XDocument.Load(\"~/Documents/Data.xml\");\nmyObject = serializer.Deserialize(xmlDocument);\n```\n\nYou can also optionally deserialize into an already existing object(primarily useful for usage in Unity3d where you do not have the ability to manually create some object instances).\n\n```csharp\nxmlDocument = XDocument.Load(\"~/Documents/Data.xml\");\nserializer.Deserialize(xmlDocument, myObject);\n```\n\n### Extension\n\nThe base serializer aims to provide a good amount of extensibility in the form of custom serializer implementations.\n\n#### IBaseSerializer\n\nAll serializers must implement the `IBaseSerializer` interface which contains various properties and methods required for serialization and deserialization.\n\n##### Order\n\n```csharp\nint Order { get; }\n```\n\nThe order of this serializer. Serializers with a higher order will be considered first. This can be useful if several serializers would clash with each other.\n\n##### IsHandled\n\n```csharp\nbool IsHandled(SerializationContext.Ref reference);\n```\n\nChecks if the given type can be handled by this serializer. If this method returns true we indicate that this serializer is willing and ready to deserialize the given reference.\n\nThe `Ref` type is a commonly used container type to safely dereference objects in the base inspector. See below for documentation on its public API.\n\n##### Serialize\n\n```csharp\nvoid Serialize(SerializationContext.Ref target, SerializationContext context);\n```\n\nSerializes the given value. The amount of parameters might look confusing, but the `Ref` contains both the object that should be serialized aswell as the XML element it should be serialized into.\n\nThe `SerializationContext` holds data about the ongoing serialization process and the `BaseSerializer` instance contains methods to serialize child values. See below for documentation on its public API.\n\n##### CreateInstance\n\n```csharp\nobject CreateInstance(SerializationContext.Ref source);\n```\n\nCreates an instance from deserialized data. The instance must not be populated right away, but an instance must be created and used later on.\n\nThis method is essential to the base inspectors special handling of references. Try to do as little work here as possible, just the bare minimum necessary to construct an object.\n\n##### Deserialize\n\n```csharp\nvoid Deserialize(SerializationContext.Ref source, SerializationContext context);\n```\n\nThis method performans the actual deserilization. You can go wild with your deserilization logic here. The object previously created by `CreateInstance` can be found inside the `Ref`.\n\nThis method is not guaranteed to immediately run after `CreateInstance` and execution could be stalled in case of cyclic references until the hierarchy has been unwinded.\n\n#### Ref\n\nThe `Ref`(or `SerializationContext.Ref`) type is used to hold and safely dereference objects within the base serializer and contains some metadata in addition to the object itself.\n\n##### Type\n\n```csharp\npublic Type Type { get; }\n```\n\nThe type of the object. If the objet is `null` this property is also `null`.\n\n##### Serializer\n\n```csharp\npublic BaseSerializer Serializer { get; }\n```\n\nThe serializer associated with this reference. If the object is `null` this property may also be `null`. It is recommended to instead rely on the `Serializer` property in the context, which is never `null`.\n\n##### Id\n\n```csharp\npublic string Id { get; }\n```\n\nEvery reference has a unique ID. This property can be used to obtain the ID of the reference. This is what you typically want to store if you implement a custom serializer that has child values it needs to serialize.\n\n##### Object\n\n```csharp\npublic object Object { get; }\n```\n\nThe actual object associated with this reference.\n\n##### Element\n\n```csharp\npublic XElement Element { get; }\n```\n\nThe XML element that represents this reference. Use this to write all data to that is required from deserialization later.\n\n#### SerializationContext\n\nA `SerializationContext` is used during a single serilization or deserialization execution and holds data relevant to this process.\n\n##### Serializer\n\n```csharp\npublic BaseSerializer Serializer { get; }\n```\n\nThe serializer associated with this context.\n\n#### BaseSerializer\n\n##### Serializers\n\n```csharp\npublic IList\u003cIBaseSerializer\u003e Serializers { get; }\n```\n\nThe base serializer delegates the handling of individual data types to different serializer implementations. You can get/add/change all implementations use by a base serializer though its `Serializers` property.\n\nContains `FallbackSerializer.Instance`, `IntegerSerializer.Instance`,  `StringSerializer.Instance` \u0026 `FloatSerializer.Instance` by default.\n\n##### AssemblyAliases\n\n```csharp\npublic IDictionary\u003cstring, Assembly\u003e AssemblyAliases { get; }\n```\n\nSince the base serializer also saves the type these aliases can be used to shorten the type name. The default names are rather long(`/YourApp.NameSpace.YourClass+ChildClass, App, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`), but with an alias it can be shortened significantly(`app/YourApp.NameSpace.YourClass+ChildClass` - in this case, `app` was used as alias for the `App` assembly.).\n\nContains `mscorlib` as an alias for the .NET standard library and `serializer` for the base serializer assembly by default.\n\n##### Serialize\n\n```csharp\npublic XDocument Serialize(object data)\n```\n\nThis method serializes the given object as a XML document.\n\n##### Deserialize\n\n```csharp\npublic object Deserialize(XDocument document)\npublic void Deserialize(XDocument document, object target)\n```\n\nDeserializes either the given XML document into a new object(first variant), or into an already existing object(primarily useful for usage in Unity3d where you do not have the ability to manually create some object instances).\n\n##### SerializeReference\n\n```csharp\npublic SerializationContext.Ref SerializeReference(object data, SerializationContext ctx)\n```\n\nSerializes the given object into a `Ref`. If the object has been serialized before its `Ref` will be reused. This method is meant to be used inside of custom serializers. See examples below for further details.\n\n##### DeserializeReference\n\n```csharp\npublic SerializationContext.Ref DeserializeReference(string id, SerializationContext ctx)\n```\n\nThis method deserializes an object. Pass the ID of a reference and it will return the fully deserialized `Ref`(or null if the ID does not exist). See examples below for further details.\n\n### Examples\n\nAll examples mentioned here can be found(with some minor modifications) in `Test/Examples` directory. In genereal the `Test` directiory is a good place to look if you are unsure on how to use the public API of the base serializer.\n\n#### Simple Serialization\n\nThe code can be found here: `Test/Examples/SimpleSerialization.cs` \n\nFirst of all we'll create a simple class to serialize:\n\n```csharp\npublic class UserAccount\n{\n    public string Name;\n    public string Gender;\n    public int Age;\n\n    public UserAccount(string name, string gender, int age)\n    {\n        Name = name;\n        Gender = gender;\n        Age = age;\n    }\n}\n```\n\nBy default the base serializer only serializes fields, so we'll just use simple public fields for everything. If you want to serialize properties there is an example in the `Test/Examples` directory for that aswell.\n\nNow let's get to writing the actual save method. \n\n```csharp\npublic void SaveData()\n{\n    UserAccount account = new UserAccount(\"Mike Johnson\", \"Male\", 36);\n\n    BaseSerializer serializer = new BaseSerializer();\n    XDocument document = serializer.Serialize(account);\n    document.Save(\"~/Documents/Data.xml\");\n}\n```\n\nThis will create the following `Data.xml` file:\n\n```xml\n\u003cData root=\"ref-1\"\u003e\n  \u003cref-1 type=\"/Test.Examples.SimpleSerialization+UserAccount, Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null\"\u003e\n    \u003cName\u003eref-2\u003c/Name\u003e\n    \u003cGender\u003eref-3\u003c/Gender\u003e\n    \u003cAge\u003eref-4\u003c/Age\u003e\n  \u003c/ref-1\u003e\n  \u003cref-2 type=\"mscorlib/System.String\"\u003eMike Johnson\u003c/ref-2\u003e\n  \u003cref-3 type=\"mscorlib/System.String\"\u003eMale\u003c/ref-3\u003e\n  \u003cref-4 type=\"mscorlib/System.Int32\"\u003e36\u003c/ref-4\u003e\n\u003c/Data\u003e\n```\n\nEvery field has been serialized into its own reference.\n\n#### Cyclic Serialization\n\nThe code can be found here: `Test/Examples/CyclicSerialization.cs` \n\nHowever not all values are typically simple primitives. In a language such as C# we heavily work with classes having references to each other, which has a possibility to introduce cyclic references.\n\nTo demonstrate this let's add another field to the `UserAccount` class: A list of friends.\n\n```csharp\npublic IList\u003cUserAccount\u003e Friends = new List\u003cUserAccount\u003e();\n```\n\nNow let's create some cyclic user accounts.\n\n```csharp\npublic void SaveData()\n{\n    UserAccount account = new UserAccount(\"Mike Johnson\", \"Male\", 36);\n    UserAccount jane = new UserAccount(\"Jane Doe\", \"Female\", 42);\n    UserAccount john = new UserAccount(\"John Harper\", \"Male\", 57);\n    account.Friends.Add(jane);\n    account.Friends.Add(john);\n    jane.Friends.Add(john);\n    john.Friends.Add(jane);\n    \n    BaseSerializer serializer = new BaseSerializer();\n    XDocument document = serializer.Serialize(account);\n    document.Save(\"~/Documents/Data.xml\");\n}\n```\n\nAnd the output is(behold!):\n\n```xml\n\u003cData root=\"ref-1\"\u003e\n  \u003cref-1 type=\"/Test.Examples.CyclicSerialization+UserAccount, Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null\"\u003e\n    \u003cName\u003eref-2\u003c/Name\u003e\n    \u003cGender\u003eref-3\u003c/Gender\u003e\n    \u003cAge\u003eref-4\u003c/Age\u003e\n    \u003cFriends\u003eref-5\u003c/Friends\u003e\n  \u003c/ref-1\u003e\n  \u003cref-2 type=\"mscorlib/System.String\"\u003eMike Johnson\u003c/ref-2\u003e\n  \u003cref-3 type=\"mscorlib/System.String\"\u003eMale\u003c/ref-3\u003e\n  \u003cref-4 type=\"mscorlib/System.Int32\"\u003e36\u003c/ref-4\u003e\n  \u003cref-5 type=\"mscorlib/System.Collections.Generic.List`1[[Test.Examples.CyclicSerialization+UserAccount, Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]\"\u003e\n    \u003cEntry\u003eref-6\u003c/Entry\u003e\n  \u003c/ref-5\u003e\n  \u003cref-6 type=\"/Test.Examples.CyclicSerialization+UserAccount, Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null\"\u003e\n    \u003cName\u003eref-7\u003c/Name\u003e\n    \u003cGender\u003eref-3\u003c/Gender\u003e\n    \u003cAge\u003eref-8\u003c/Age\u003e\n    \u003cFriends\u003eref-9\u003c/Friends\u003e\n  \u003c/ref-6\u003e\n  \u003cref-7 type=\"mscorlib/System.String\"\u003eJohn Harper\u003c/ref-7\u003e\n  \u003cref-8 type=\"mscorlib/System.Int32\"\u003e57\u003c/ref-8\u003e\n  \u003cref-9 type=\"mscorlib/System.Collections.Generic.List`1[[Test.Examples.CyclicSerialization+UserAccount, Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]\"\u003e\n    \u003cEntry\u003eref-1\u003c/Entry\u003e\n  \u003c/ref-9\u003e\n\u003c/Data\u003e\n```\n\nLet's take a look at this structure: Our root `\u003cData\u003e` node has an attribute called `root`. This where our object begins. In our case this is `ref-1`, which is just a line below.\n\nIts `\u003cFriends\u003e` node references our list of friends(`account.Friends`) at `ref-5`. This list has an entry for John(`ref-6`) which in turn has a friends list(`ref-9`) that contains an entry back to `ref-1`.\n\nFurthermore you may have noticed that the `\u003cGender\u003e` of both Mike and John uses `ref-3`. Since everything is handled using the reference system internally no value will be serialized twice.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsachskaylee%2Fbaseserializer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsachskaylee%2Fbaseserializer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsachskaylee%2Fbaseserializer/lists"}