{"id":24475688,"url":"https://github.com/angl-dev/object-oriented-serializer","last_synced_at":"2025-03-14T16:13:19.575Z","repository":{"id":76731287,"uuid":"154163952","full_name":"angl-dev/object-oriented-serializer","owner":"angl-dev","description":"A memory-efficient object-oriented data serialization library","archived":false,"fork":false,"pushed_at":"2018-11-01T21:20:49.000Z","size":23,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-21T09:32:16.797Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","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/angl-dev.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-10-22T15:02:54.000Z","updated_at":"2018-11-01T21:20:51.000Z","dependencies_parsed_at":"2023-02-27T03:31:44.393Z","dependency_job_id":null,"html_url":"https://github.com/angl-dev/object-oriented-serializer","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/angl-dev%2Fobject-oriented-serializer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/angl-dev%2Fobject-oriented-serializer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/angl-dev%2Fobject-oriented-serializer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/angl-dev%2Fobject-oriented-serializer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/angl-dev","download_url":"https://codeload.github.com/angl-dev/object-oriented-serializer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243606962,"owners_count":20318314,"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":[],"created_at":"2025-01-21T09:26:55.983Z","updated_at":"2025-03-14T16:13:19.560Z","avatar_url":"https://github.com/angl-dev.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Memory-efficient data serialization library\n\n## Design goals \n1. Memory efficiency:\n    * Low memory overhead for the objects\n    * Generator-based serialization \u0026 deserialization\n2. Serialization schema:\n    * Define data schema with `class`es and `property`-like decorators\n    * Use (multi-) inheritance to extend, modify and combine schemas\n3. User interface:\n    * Detailed error report for data that don't match the defined schema\n\n## Vocabulary\n\nTo minimize possible confusions of the description below, we define the\nfollowing vocabulary:\n\n* **serializable class**: a class inheriting the `Serializable` class\n* **serializable object**: an instance of a serializable class\n* **serializable property**: a `SerializableAttribute`,\n    `SerializableChildObject` or `SerializableTextContent` property of a\n    serializable class\n* **key**: key in the serialized format, that is, tag in XML, key in JSON/YAML\n\n## Basic usage\n\nThe key class is the `Serializable` class. Inherit this class to create a\nschema for serializable objects. Use `SerializableAttribute`,\n`SerializableChildObject` and `SerializableTextContent` to add schema on the\ncorresponding contents to this object.\n\nA simple example:\n\n```python\nfrom serializer import *\n\nclass Animal(Serializable):\n    type = SerializableAttribute(required=True)\n    description = SerializableTextContent()\n\nclass Zoo(Serializable):\n    animal = SerializableChildObject(Animal, required=True, multiple=True)\n```\n\nUse `deserialize_xml` to deserialize a XML file with a serializable class\n(`deserialize_json` and `deserialize_yaml` will be added later). This function\ntakes three arguments, the first being a file-like object to deserialize from,\nthe second being the root key, and the third being a factory function which\ncan create serializable objects (could be the serializable class itself).\n\n```python\nfrom StringIO import StringIO\nzoo = deserialize_xml(StringIO('''\n    \u003czoo\u003e\n        \u003canimal type=\"cat\"\u003eThe cat, often referred to as the domestic cat to\n        distinguish from other felids and felines, is a small, typically\n        furry, carnivorous mammal.\u003c/animal\u003e\n        \u003canimal type=\"dog\"\u003eThe domestic dog is a member of the genus Canis,\n        which forms part of the wolf-like canids, and is the most widely\n        abundant terrestrial carnivore.\u003c/animal\u003e\n    \u003c/zoo\u003e\n    '''), 'zoo', Zoo)\n```\n\nAfter deserialization, the serializable object `zoo` has everything stored in\nit. All serializable properties can be accessed just like normal properties.\n\n```python\nfor animal in zoo.animal:\n    print animal.type\n# output\n# \u003e cat\n# \u003e dog\n```\n\nIn addition to deserializing from a file, serializable objects can also be\ncreated and modified in the Python program.\n\n```python\ncow = Animal(type='cow')\ncow.description=(\"Cattle-colloquially cows-are the most common type of large \"\n    \"domesticated ungulates.\")\nzoo.animal.append(cow)\n```\n\n[_Pitfalls_: uninitialized properties](#uninitialized-properties)\n\nFinally, use `serialize_xml` to serialize to a XML file (`serialze_json` and\n`serialize_yaml` will be added later). This function also takes three\narguments, the first being a file-like object to deserialize to , the second\nbeing the root key, and the third being a serializable object. An optional\nargument is `pretty`, which enables pretty printing, and is set to `False` by\ndefault.\n\n```python\noutstream = StringIO()\nserialize_xml(outstream, 'zoo', zoo, pretty=True)\nprint outstream.getvalue()\n# output\n# \u003e \u003czoo\u003e\n# \u003e     \u003canimal type=\"cat\"\u003eThe cat, often referred to as the domestic cat to\n# \u003e     distinguish from other felids and felines, is a small, typically\n# \u003e     furry, carnivorous mammal.\u003c/animal\u003e\n# \u003e     \u003canimal type=\"dog\"\u003eThe domestic dog is a member of the genus Canis,\n# \u003e     which forms part of the wolf-like canids, and is the most widely\n# \u003e     abundant terrestrial carnivore.\u003c/animal\u003e\n# \u003e     \u003canimal type=\"cow\"\u003eCattle-colloquially cows-are the most common type\n# \u003e     of large domesticated ungulates.\u003c/animal\u003e\n# \u003e \u003c/zoo\u003e\n```\n\n## Advanced usage I: Combine schemas\n\nIt's possible to inherit serializable classes to extend or combine schemas.\nNote that it's also possible to override some serializable properties with\nregular properties or methods, and they simply follow Python's MRO.\n\n```python\nclass AnimalCategory(Animal):\n    @property\n    def description(self):  # remove the text content from the schema\n        raise NotImplementedError\n\n    subtype = SerializableChildObject(Animal, required=True, multiple=True)\n\nclass BetterZoo(Zoo):\n    category = SerializableChildObject(AnimalCategory, required=True,\n        multiple=True)\n\nzoo2 = deserialize_xml(StringIO('\u003czoo\u003e\u003ccategory type=\"mammal\"\u003e'\n    '\u003csubtype type=\"human\"\u003eHumans (taxonomically, Homo sapiens) are the only '\n    'extant members of the subtribe Hominina.\u003c/subtype\u003e'\n    '\u003csubtype type=\"whale\"\u003eWhales are a widely distributed and diverse group '\n    'of fully aquatic placental marine mammals.\u003c/subtype\u003e'\n    '\u003c/category\u003e\u003canimal type=\"fish\"\u003eFish are gill-bearing aquatic craniate '\n    'animals that lack limbs with digits.\u003c/animal\u003e\u003c/zoo\u003e'),\n    'zoo', BetterZoo)\n\nfor category in zoo2.category:\n    for subtype in category.subtype:\n        print subtype.type\nfor animal in zoo2.animal:\n    print animal.type\n# output\n# \u003e human\n# \u003e whale\n# \u003e fish\n```\n\n## Advanced usage II: Advanced serializable properties\n\nSometimes we want the key and property name of a serializable property to be\ndifferent. For example, the key might be a reserved keyword in Python. Use\n`key` in `SerializableAttribute`, `SerializableChildObject` and\n`SerializableTextContent` to specify a different key.\n\n`SerializableAttribute`, `SerializableChildObject` and\n`SerializableTextContent` can also be used just like Python's built-in\n`property` decorator. Besides, XML, JSON and YAML only support a limited\nnumber of basic data types, but we often want to have some more specific type\nof data. So, `SerializableAttribute` and `SerializableTextContent` also have\n`serializer` and `serializer` methods which can be used to convert between\ncustom data types and basic data types.\n\n```python\nclass DetailedAnimal(Animal):\n    features = SerializableAttribute(required=False, key='feature')\n\n    @features.deserializer\n    def features(s):\n        return s.split()\n\n    @features.serializer\n    def features(v):\n        return ' '.join(v)\n\nanimal = deserialize_xml(StringIO('\u003canimal type=\"bird\" feature=\"fly sing\"\u003e'\n    'Birds, also known as Aves, are a group of endothermic vertebrates, '\n    'characterised by feathers, toothless beaked jaws, the laying of '\n    'hard-shelled eggs, a high metabolic rate, a four-chambered heart, and a '\n    'strong yet lightweight skeleton.\u003c/animal\u003e'), 'animal', DetailedAnimal)\nfor feature in animal.features:\n    print feature\n\n# output\n# \u003e fly\n# \u003e sing\n```\n\nIt's also possible to ask the serializer to ignore a serializable property.\nReturn `IGNORE` in the `serializer` method to do so.\n\n## Advanced usage III: Fully customized serialization \u0026 deserialization\n\n## Pitfalls\n\n### Uninitialized Properties\n\nA `SerializableAttribute`, `SerializableChildObject`, and\n`SerializableTextContent` property are uninitialized when a serializable\nobject is created, unless:\n1. a `default` value is set when defining the property\n2. the property is set with argument passed to `__init__`\n3. the property is deserialized from a file\n\nIf a property is uninitialized, accessing it will raise a\n`SerializableAttributeError`. To avoid complex logic checking if a\nserializable property is initialized, always define `default` value, or set it\nin the inherited `__init__`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fangl-dev%2Fobject-oriented-serializer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fangl-dev%2Fobject-oriented-serializer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fangl-dev%2Fobject-oriented-serializer/lists"}