{"id":28171332,"url":"https://github.com/okthought/data-mapper","last_synced_at":"2025-05-15T18:18:55.038Z","repository":{"id":57417914,"uuid":"198879276","full_name":"OkThought/data-mapper","owner":"OkThought","description":"A declarative data mapper","archived":false,"fork":false,"pushed_at":"2019-10-13T04:26:44.000Z","size":204,"stargazers_count":13,"open_issues_count":1,"forks_count":3,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-05-15T18:18:53.877Z","etag":null,"topics":["data","mapper","python"],"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/OkThought.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}},"created_at":"2019-07-25T18:03:10.000Z","updated_at":"2023-06-11T17:21:22.000Z","dependencies_parsed_at":"2022-09-03T09:41:10.718Z","dependency_job_id":null,"html_url":"https://github.com/OkThought/data-mapper","commit_stats":null,"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OkThought%2Fdata-mapper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OkThought%2Fdata-mapper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OkThought%2Fdata-mapper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OkThought%2Fdata-mapper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/OkThought","download_url":"https://codeload.github.com/OkThought/data-mapper/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254394655,"owners_count":22063985,"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":["data","mapper","python"],"created_at":"2025-05-15T18:18:45.230Z","updated_at":"2025-05-15T18:18:55.021Z","avatar_url":"https://github.com/OkThought.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# data-mapper\nA declarative data mapper\n\n![PyPI](https://img.shields.io/pypi/v/data-mapper?style=for-the-badge)\n![Travis (.org) branch](https://img.shields.io/travis/OkThought/data-mapper/master?logo=travis\u0026style=for-the-badge)\n\n## Disclaimer\nI don't know if anyone uses this library except for me so I'm not\nputting much effort in writing good documentation. If you are using it\nor just thinking about using it, give me a sign of your attention (e.g.\nstar this repo, or open an issue) and this will definitely motivate me\nto do it ;)\n\n## Description\n\nMost projects work with different representations of the same data.\nThe code that is written every time to morph data between its representations\nis mostly very repetitive. More over, it is always a deposit of bugs and issues\nwhich requires a developer or tester to unit-test it.\n\nThis package is an attempt to solve these problems... well, at least the most\ncommon ones.\n\nAnd to make a developer job easier it is primarily designed to be used\nin declarative fashion: describe what you want and get it right after.\n\n## Use Cases and Features\n\nHere are examples of the most common use-cases and features: \n\n### Different Naming Schemes\n\nThis mapper looks for properties `first_name` and `last_name` in the data.\nFor property `first_name` it tries to resolve it by the first key \n`'first_name'`, if not found it tries the second key `'name'`.\nThe similar process goes for property `last_name`.\n\n```python\nfrom data_mapper.mappers import Mapper\nfrom data_mapper.properties import Property\n\nclass PersonMapper(Mapper):\n    first_name = Property('first_name', 'name')\n    last_name = Property('last_name', 'surname')\n\nmapper = PersonMapper()\n\nassert mapper.get({\n    'first_name': 'Ivan', \n    'surname': 'Bogush',\n}) == {\n    'first_name': 'Ivan', \n    'last_name': 'Bogush',\n}\n\nassert mapper.get({\n    'name': 'Ivan', \n    'surname': 'Bogush',\n}) == {\n    'first_name': 'Ivan', \n    'last_name': 'Bogush',\n}\n```\n\nThis use-case has a story :)\n\u003e It was the first issue I wanted to solve in my other project. I had different \nnaming schemes in different data sources, and in my databases. All of them used \ndifferent names for product categories: 'categories', 'category', 'categoryId'.\nI found it very boring to write repeatable code to convert the same data.\n\n### Arbitrary functions on resolved values\n\n#### Full Name String Construction\nThis one resolves properties `first_name`, `middle_name` [optionally] and \n`last_name` and combines them into a single string — `full_name`.\n\n```python\nfrom data_mapper.shortcuts import F, Str, L\n\nfull_name = F(\n    ' '.join,\n    L(\n        Str('first_name'),\n        Str('middle_name', required=False),\n        Str('last_name'),\n        skip_none=True,\n    ),\n)\n\nassert 'Anton Pavlovich Chekhov' == full_name.get(dict(\n    first_name='Anton',\n    middle_name='Pavlovich',\n    last_name='Chekhov',\n))\n\nassert 'Anton Chekhov' == full_name.get(dict(\n    first_name='Anton',\n    last_name='Chekhov',\n))\n```\n\n### Object mapping\n\n#### Dict to *Object*\n\nLet's assume we have a class `Person`:\n```python\nclass Person:\n    def __init__(\n            self,\n            id_: int,\n            first_name: str,\n            last_name: str,\n            middle_name: str = None,\n    ):\n        self.id = id_\n        self.first_name = first_name\n        self.last_name = last_name\n        self.middle_name = middle_name\n```\n\nA mapper from dict with corresponding keys to an instance of class `Person` \ncould be defined by subclassing `ObjectMapper`:\n\n```python\nfrom data_mapper.mappers.object import ObjectMapper\nfrom data_mapper.properties import (\n    CompoundProperty, CompoundListProperty, IntegerProperty, StringProperty,\n)\n\n\nclass PersonMapper(ObjectMapper):\n    init = Person\n    args = CompoundListProperty(\n        IntegerProperty('id'),\n        StringProperty('first_name'),\n        StringProperty('last_name'),\n    )\n    kwargs = CompoundProperty(\n        middle_name=StringProperty(required=False),\n    )\n\nfirst, middle, last = 'Iosif Aleksandrovich Brodsky'.split()\nperson = PersonMapper().get(dict(\n    id=1940,\n    first_name=first,\n    middle_name=middle,\n    last_name=last,\n))\n\nassert isinstance(person, Person)\nassert person.id == 1940\nassert person.first_name == first\nassert person.middle_name == middle\nassert person.last_name == last\n```\n\nExactly the same can be done by instantiating the `ObjectMapper`:\n\n```python\nfrom data_mapper.mappers.object import ObjectMapper\nfrom data_mapper.properties import (\n    CompoundProperty, CompoundListProperty, IntegerProperty, StringProperty,\n)\n\n\nmapper = ObjectMapper(\n    init=Person,\n    args=CompoundListProperty(\n        IntegerProperty('id'),\n        StringProperty('first_name'),\n        StringProperty('last_name'),\n    ),\n    kwargs=CompoundProperty(\n        middle_name=StringProperty(required=False),\n    ),\n)\n\nfirst, middle, last = 'Iosif Aleksandrovich Brodsky'.split()\nperson = mapper.get(dict(\n    id=1940,\n    first_name=first,\n    middle_name=middle,\n    last_name=last,\n))\n\nassert isinstance(person, Person)\nassert person.id == 1940\nassert person.first_name == first\nassert person.middle_name == middle\nassert person.last_name == last\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fokthought%2Fdata-mapper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fokthought%2Fdata-mapper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fokthought%2Fdata-mapper/lists"}