{ "info": { "author": "bogdandm (Bogdan Kalashnikov)", "author_email": "bogdan.dm1995@yandex.ru", "bugtrack_url": null, "classifiers": [], "description": "[![json2python-models](https://raw.githubusercontent.com/bogdandm/json2python-models/master/etc/logo.png)](https://github.com/bogdandm/json2python-models)\n\n[![PyPI version](https://img.shields.io/pypi/v/json2python-models.svg?color=green)](https://badge.fury.io/py/json2python-models)\n[![Build Status](https://travis-ci.org/bogdandm/json2python-models.svg?branch=master)](https://travis-ci.org/bogdandm/json2python-models)\n[![Coverage Status](https://coveralls.io/repos/github/bogdandm/json2python-models/badge.svg?branch=master)](https://coveralls.io/github/bogdandm/json2python-models?branch=master)\n[![Codacy Badge](https://api.codacy.com/project/badge/Grade/11e13f2b81d7450eb0bca4b941d16d81)](https://www.codacy.com/app/bogdandm/json2python-models?utm_source=github.com&utm_medium=referral&utm_content=bogdandm/json2python-models&utm_campaign=Badge_Grade)\n\n![Example](https://raw.githubusercontent.com/bogdandm/json2python-models/master/etc/convert.png)\n\njson2python-models is a [Python](https://www.python.org/) tool that can generate Python models classes \n(dataclasses, [attrs](https://github.com/python-attrs/attrs)) from JSON dataset. \n\n## Features\n\n* Full **`typing` module** support\n* **Types merging** - if some field contains data of different types this will be represent as `Union` type\n* Fields and models **names** generation (unicode support included)\n* Similar **models generalization**\n* Handling **recursive data** structures (i.e family tree)\n* Detecting **string literals** (i.e. datetime or just stringify numbers) \n and providing decorators to easily convert into Python representation\n* Generation models as **tree** (nested models) or **list**\n* Specifying when dictionaries should be processed as **`dict` type** (by default every dict is considered as some model)\n* **CLI** tool\n\n## Table of Contents\n\n* [Features](#features)\n* [Table of Contents](#table-of-contents)\n* [Example](#example)\n* [Installation](#installation)\n* [Usage](#usage)\n * [CLI](#cli)\n * [Low level API]()\n* [Tests](#tests)\n * [Test examples](#test-examples)\n* [Built With](#built-with)\n* [Contributing](#contributing)\n* [License](#license)\n\n## Example\n\n### F1 Season Results\n\n
Show (long code)\n

\n\n```\ndriver_standings.json\n[\n {\n \"season\": \"2019\",\n \"round\": \"3\",\n \"DriverStandings\": [\n {\n \"position\": \"1\",\n \"positionText\": \"1\",\n \"points\": \"68\",\n \"wins\": \"2\",\n \"Driver\": {\n \"driverId\": \"hamilton\",\n \"permanentNumber\": \"44\",\n \"code\": \"HAM\",\n \"url\": \"http://en.wikipedia.org/wiki/Lewis_Hamilton\",\n \"givenName\": \"Lewis\",\n \"familyName\": \"Hamilton\",\n \"dateOfBirth\": \"1985-01-07\",\n \"nationality\": \"British\"\n },\n \"Constructors\": [\n {\n \"constructorId\": \"mercedes\",\n \"url\": \"http://en.wikipedia.org/wiki/Mercedes-Benz_in_Formula_One\",\n \"name\": \"Mercedes\",\n \"nationality\": \"German\"\n }\n ]\n },\n ...\n ]\n }\n]\n```\n\n```\njson2models -f attrs -l DriverStandings driver_standings.json\n```\n\n```python\nimport attr\nfrom json_to_models.dynamic_typing import IntString, IsoDateString\nfrom typing import List\n\n\n@attr.s\nclass DriverStandings:\n @attr.s\n class DriverStanding:\n @attr.s\n class Driver:\n driver_id: str = attr.ib()\n permanent_number: IntString = attr.ib(converter=IntString)\n code: str = attr.ib()\n url: str = attr.ib()\n given_name: str = attr.ib()\n family_name: str = attr.ib()\n date_of_birth: IsoDateString = attr.ib(converter=IsoDateString)\n nationality: str = attr.ib()\n \n @attr.s\n class Constructor:\n constructor_id: str = attr.ib()\n url: str = attr.ib()\n name: str = attr.ib()\n nationality: str = attr.ib()\n \n position: IntString = attr.ib(converter=IntString)\n position_text: IntString = attr.ib(converter=IntString)\n points: IntString = attr.ib(converter=IntString)\n wins: IntString = attr.ib(converter=IntString)\n driver: 'Driver' = attr.ib()\n constructors: List['Constructor'] = attr.ib()\n\n season: IntString = attr.ib(converter=IntString)\n round: IntString = attr.ib(converter=IntString)\n driver_standings: List['DriverStanding'] = attr.ib()\n```\n\n

\n
\n\n### Swagger\n\n
Show (long code)\n

\n\n`swagger.json` from any online API (I tested file generated by drf-yasg and another one for Spotify API)\n\nIt requires a lit bit of tweaking:\n* Some fields store routes/models specs as dicts\n* There is a lot of optinal fields so we reduce merging threshold \n\n```\njson_to_models -s flat -f dataclasses -m Swagger testing_tools/swagger.json \n --dict-keys-fields securityDefinitions paths responses definitions properties \n --merge percent_50 number\n```\n\n```python\nfrom dataclasses import dataclass, field\nfrom json_to_models.dynamic_typing import FloatString\nfrom typing import Any, Dict, List, Optional, Union\n\n\n@dataclass\nclass Swagger:\n swagger: FloatString\n info: 'Info'\n host: str\n schemes: List[str]\n base_path: str\n consumes: List[str]\n produces: List[str]\n security_definitions: Dict[str, 'Parameter_SecurityDefinition']\n security: List['Security']\n paths: Dict[str, 'Path']\n definitions: Dict[str, 'Definition_Schema']\n\n\n@dataclass\nclass Info:\n title: str\n description: str\n version: str\n\n\n@dataclass\nclass Security:\n api_key: Optional[List[Any]] = field(default_factory=list)\n basic: Optional[List[Any]] = field(default_factory=list)\n\n\n@dataclass\nclass Path:\n parameters: List['Parameter_SecurityDefinition']\n post: Optional['Delete_Get_Patch_Post_Put'] = None\n get: Optional['Delete_Get_Patch_Post_Put'] = None\n put: Optional['Delete_Get_Patch_Post_Put'] = None\n patch: Optional['Delete_Get_Patch_Post_Put'] = None\n delete: Optional['Delete_Get_Patch_Post_Put'] = None\n\n\n@dataclass\nclass Property:\n type: str\n format: Optional[str] = None\n xnullable: Optional[bool] = None\n items: Optional['Item_Schema'] = None\n\n\n@dataclass\nclass Property_2E:\n type: str\n title: Optional[str] = None\n read_only: Optional[bool] = None\n max_length: Optional[int] = None\n min_length: Optional[int] = None\n items: Optional['Item'] = None\n enum: Optional[List[str]] = field(default_factory=list)\n maximum: Optional[int] = None\n minimum: Optional[int] = None\n format: Optional[str] = None\n\n\n@dataclass\nclass Item:\n ref: Optional[str] = None\n title: Optional[str] = None\n type: Optional[str] = None\n max_length: Optional[int] = None\n min_length: Optional[int] = None\n\n\n@dataclass\nclass Parameter_SecurityDefinition:\n name: str\n in_: str\n required: Optional[bool] = None\n schema: Optional['Item_Schema'] = None\n type: Optional[str] = None\n description: Optional[str] = None\n\n\n@dataclass\nclass Delete_Get_Patch_Post_Put:\n operation_id: str\n description: str\n parameters: List['Parameter_SecurityDefinition']\n responses: Dict[str, 'Response']\n tags: List[str]\n\n\n@dataclass\nclass Item_Schema:\n ref: str\n\n\n@dataclass\nclass Response:\n description: str\n schema: Optional[Union['Item_Schema', 'Definition_Schema']] = None\n\n\n@dataclass\nclass Definition_Schema:\n ref: Optional[str] = None\n required: Optional[List[str]] = field(default_factory=list)\n type: Optional[str] = None\n properties: Optional[Dict[str, Union['Property_2E', 'Property']]] = field(default_factory=dict)\n```\n\n

\n
\n\n## Installation\n\n| **Be ware**: this project supports only `python3.7` and higher. |\n| --- |\n\nTo install it, use `pip`:\n\n`pip install json2python-models`\n\nOr you can build it from source:\n\n```\ngit clone https://github.com/bogdandm/json2python-models.git\ncd json2python-models\npython setup.py install\n```\n\n## Usage\n\n### CLI\n\nFor regular usage CLI tool is the best option. After you install this package you could use it as `json2models ` \nor `python -m json_to_models `. I.e.:\n```\njson2models -m Car car_*.json -f attrs > car.py\n```\n\nArguments:\n* `-h`, `--help` - Show help message and exit\n \n* `-m`, `--model` - Model name and its JSON data as path or unix-like path pattern. `*`, `**` or `?` patterns symbols are supported.\n * **Format**: `-m [ ...]`\n * **Example**: `-m Car audi.json reno.json` or `-m Car audi.json -m Car reno.json` (results will be the same)\n \n* `-l`, `--list` - Like `-m` but given json file should contain list of model data (dataset). \n If this file contains dict with nested list than you can pass `` to lookup. \n Deep lookups are supported by dot-separated path. If no lookup needed pass `-` as ``.\n * **Format**: `-l `\n * **Example**: `-l Car - cars.json -l Person fetch_results.items.persons result.json`\n * **Note**: Models names under this arguments should be unique.\n \n* `-o`, `--output` - Output file\n * **Format**: `-o `\n * **Example**: `-o car_model.py`\n \n* `-f`, `--framework` - Model framework for which python code is generated. \n `base` (default) mean no framework so code will be generated without any decorators and additional meta-data.\n * **Format**: `-f {base,attrs,dataclasses,custom}`\n * **Example**: `-f attrs`\n * **Default**: `-f base`\n \n* `-s`, `--structure` - Models composition style.\n * **Format**: `-s {nested, flat}` \n * **Example**: `-s flat`\n * **Default**: `-s nested`\n \n* `--datetime` - Enable datetime/date/time strings parsing.\n * **Default**: disabled\n * **Warning**: This can lead to 6-7 times slowdown on large datasets. Be sure that you really need this option.\n \n* `--disable-unicode-conversion`, `--no-unidecode` - Disable unicode conversion in field labels and class names\n * **Default**: enabled\n \n* `--strings-converters` - Enable generation of string types converters (i.e. `IsoDatetimeString` or `BooleanString`).\n * **Default**: disabled\n\n* `--merge` - Merge policy settings. Possible values are: \n * **Format**: `--merge MERGE_POLICY [MERGE_POLICY ...]`\n * **Possible values** (MERGE_POLICY):\n * `percent[_]` - two models had a certain percentage of matched field names. \n Custom value could be i.e. `percent_95`. \n * `number[_]` - two models had a certain number of matched field names. \n * `exact` - two models should have exact same field names to merge.\n * **Example**: `--merge percent_95 number_20` - merge if 95% of fields are matched or 20 of fields are matched\n * **Default**: `--merge percent_70 number_10`\n \n* `--dict-keys-regex`, `--dkr` - List of regular expressions (Python syntax).\n If all keys of some dict are match one of the pattern then \n this dict will be marked as dict field but not nested model.\n * **Format**: `--dkr RegEx [RegEx ...]`\n * **Example**: `--dkr node_\\d+ \\d+_\\d+_\\d+`\n * **Note**: `^` and `$` (string borders) tokens will be added automatically but you \n have to escape other special characters manually.\n * **Optional**\n \n* `--dict-keys-fields`, `--dkf` - List of model fields names that will be marked as dict fields\n * **Format**: `--dkf FIELD_NAME [FIELD_NAME ...]`\n * **Example**: `--dkf \"dict_data\" \"mapping\"`\n * **Optional**\n \n* `--code-generator` - Absolute import path to `GenericModelCodeGenerator` subclass.\n * **Format**: `--code-generator CODE_GENERATOR`\n * **Example**: `-f mypackage.mymodule.DjangoModelsGenerator`\n * **Note**: Is ignored without `-f custom` but is required with it.\n \n* `--code-generator-kwargs` - List of GenericModelCodeGenerator subclass arguments (for `__init__` method, \n see docs of specific subclass). \n Each argument should be in following format: `argument_name=value` or `\"argument_name=value with space\"`. \n Boolean values should be passed in JS style: `true` or `false`\n * **Format**: `--code-generator-kwargs [NAME=VALUE [NAME=VALUE ...]]`\n * **Example**: `--code-generator-kwargs kwarg1=true kwarg2=10 \"kwarg3=It is string with spaces\"`\n * **Optional**\n\nOne of model arguments (`-m` or `-l`) is required.\n\n### Low level API\n\n> Coming soon (Wiki)\n\n## Tests\n\nTo run tests you should clone project and run `setup.py` script:\n\n```\ngit clone https://github.com/bogdandm/json2python-models.git\ncd json2python-models\npython setup.py test -a ''\n```\n\nAlso I would recommend you to install `pytest-sugar` for pretty printing test results\n\n### Test examples\n\nYou can find out some examples of usage of this project at [testing_tools/real_apis/...](/testing_tools/real_apis)\n\nEach file contains functions to download data from some online API (references included at the top of file) and\n`main` function that generates and prints code. Some examples may print debug data before actual code.\nDownloaded data will be saved at `testing_tools/real_apis//.json`\n\n## Built With\n\n* [python-dateutil](https://github.com/dateutil/dateutil) - Datetime parsing\n* [inflection](https://github.com/jpvanhal/inflection) - String transformations\n* [Unidecode](https://pypi.org/project/Unidecode/) - Unicode to ASCII conversion\n* [Jinja2](https://github.com/pallets/jinja) - Code templates\n* [ordered-set](https://github.com/LuminosoInsight/ordered-set) is used in models merging algorithm\n\nTest tools:\n* [pytest](https://github.com/pytest-dev/pytest) - Test framework\n* [pytest-xdist](https://github.com/pytest-dev/pytest-xdist) - Parallel execution of test suites\n* [pytest-sugar](https://github.com/Frozenball/pytest-sugar) - Test results pretty printing\n* [requests](https://github.com/kennethreitz/requests) - Test data download\n\n## Contributing\n\nFeel free to open pull requests with new features or bug fixes. Just follow few rules:\n\n1. Always use some code formatter ([black](https://github.com/ambv/black) or PyCharm built-in)\n2. Keep code coverage above 95-98%\n3. All existing tests should be passed (including test examples from `testing_tools/real_apis`)\n4. Use `typing` module\n5. Fix [codacy](https://app.codacy.com/project/bogdandm/json2python-models/dashboard) issues from your PR\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/bogdandm/json2python-models", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "json2python-models", "package_url": "https://pypi.org/project/json2python-models/", "platform": "", "project_url": "https://pypi.org/project/json2python-models/", "project_urls": { "Homepage": "https://github.com/bogdandm/json2python-models" }, "release_url": "https://pypi.org/project/json2python-models/0.1.2/", "requires_dist": null, "requires_python": ">=3.7", "summary": "Python models (attrs, dataclasses or custom) generator from JSON data with typing module support", "version": "0.1.2" }, "last_serial": 5409850, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "0e8c2484abcf008d75b2080f47572b67", "sha256": "244d81bf1957597a4adb579c0a565ad61dd4f8644bb78e0aa41942dec92faad9" }, "downloads": -1, "filename": "json2python-models-0.1.0.tar.gz", "has_sig": false, "md5_digest": "0e8c2484abcf008d75b2080f47572b67", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7", "size": 44453, "upload_time": "2019-04-24T14:38:37", "url": "https://files.pythonhosted.org/packages/0d/df/979b4c912df783bc6f45cfd54aef86ea13fe8d611547db2c01ee46c8d9ec/json2python-models-0.1.0.tar.gz" } ], "0.1.0.post1": [ { "comment_text": "", "digests": { "md5": "c7a64d1e99e2ce87edff68a8818b2022", "sha256": "73d3a51ff172d7896ff5cf47fbd52836b40065cd970be6ce1cf07f23e2c9f1cf" }, "downloads": -1, "filename": "json2python-models-0.1.0.post1.tar.gz", "has_sig": false, "md5_digest": "c7a64d1e99e2ce87edff68a8818b2022", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7", "size": 44885, "upload_time": "2019-04-24T15:09:50", "url": "https://files.pythonhosted.org/packages/3d/65/7c955ca2ada882abd5712b394e84f3ae7e32495aa3d1b2a3dbd0303ec60d/json2python-models-0.1.0.post1.tar.gz" } ], "0.1.0.post2": [ { "comment_text": "", "digests": { "md5": "7362a393378c59a6c641bbe5df064771", "sha256": "d37cf94b973f22680ce219494c1310bbf485753a81a517e85874202e50eb9a9c" }, "downloads": -1, "filename": "json2python-models-0.1.0.post2.tar.gz", "has_sig": false, "md5_digest": "7362a393378c59a6c641bbe5df064771", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7", "size": 44982, "upload_time": "2019-05-02T15:32:33", "url": "https://files.pythonhosted.org/packages/6d/81/14f699159a62a293b04fe1e45ec49b775268701d2e2cfc848996dfbbfcfc/json2python-models-0.1.0.post2.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "19b70578e9d6f78bf7715724def8aebd", "sha256": "6c431d5a4e3cec7a17f5038242bfc3b9c3cf6568b61ecbe46383680f17e81dc7" }, "downloads": -1, "filename": "json2python-models-0.1.1.tar.gz", "has_sig": false, "md5_digest": "19b70578e9d6f78bf7715724def8aebd", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7", "size": 45882, "upload_time": "2019-06-13T12:39:04", "url": "https://files.pythonhosted.org/packages/8b/12/16d4dbcc1cfd994ac29b6e1dcb059d747351221df1cd0777a7e0dab10e81/json2python-models-0.1.1.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "665cc0df9f6c76ac715ea3d3027ddb36", "sha256": "ccae1dbdb3f5b157edb06e51d4b638b7fb3a098cc000b9c6035225152dea42dd" }, "downloads": -1, "filename": "json2python-models-0.1.2.tar.gz", "has_sig": false, "md5_digest": "665cc0df9f6c76ac715ea3d3027ddb36", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7", "size": 48693, "upload_time": "2019-06-17T12:05:41", "url": "https://files.pythonhosted.org/packages/55/78/d1faab4d2983579a053ced5d0ded5df29766169dc7b33a91f12fa1d85ef8/json2python-models-0.1.2.tar.gz" } ], "0.1a1": [ { "comment_text": "", "digests": { "md5": "6932c5f51739ab18482ba1eff5e148f5", "sha256": "f7d49c4007e3611a530e5adf4a3fff7365c9f35f1bc759eaf9d605ae28fec4a2" }, "downloads": -1, "filename": "json2python-models-0.1a1.tar.gz", "has_sig": false, "md5_digest": "6932c5f51739ab18482ba1eff5e148f5", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7", "size": 33310, "upload_time": "2018-11-27T11:58:15", "url": "https://files.pythonhosted.org/packages/d7/d8/17a14743bf5fc52d20284f10a42d51db016ab573149488bd122ff0fe9765/json2python-models-0.1a1.tar.gz" } ], "0.1b1": [ { "comment_text": "", "digests": { "md5": "2e463d047ff2a0601ad24794ad4c4981", "sha256": "66372b2994e00cd3907ea87f385b5b8b74c8e5dc905a5b6a540c795b03a76f76" }, "downloads": -1, "filename": "json2python-models-0.1b1.tar.gz", "has_sig": false, "md5_digest": "2e463d047ff2a0601ad24794ad4c4981", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7", "size": 33893, "upload_time": "2018-11-27T14:40:02", "url": "https://files.pythonhosted.org/packages/73/c4/64e4e78caef3fbd80e0b3d4f4c67eae011ef05f8c543bb71855f894006e4/json2python-models-0.1b1.tar.gz" } ], "0.1b2": [ { "comment_text": "", "digests": { "md5": "ad263141435c4e1b78df996794d23fef", "sha256": "7e792d50d3f015963d28db1e2c4e1ca6f8e26da3fa41d02f722f4eaee3615f7d" }, "downloads": -1, "filename": "json2python-models-0.1b2.tar.gz", "has_sig": false, "md5_digest": "ad263141435c4e1b78df996794d23fef", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7", "size": 36119, "upload_time": "2018-11-30T16:03:23", "url": "https://files.pythonhosted.org/packages/b4/65/2839fcfe4174c6805bf3782f6bdab9484b1fbbcd8b6a347bdea94e4c90a1/json2python-models-0.1b2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "665cc0df9f6c76ac715ea3d3027ddb36", "sha256": "ccae1dbdb3f5b157edb06e51d4b638b7fb3a098cc000b9c6035225152dea42dd" }, "downloads": -1, "filename": "json2python-models-0.1.2.tar.gz", "has_sig": false, "md5_digest": "665cc0df9f6c76ac715ea3d3027ddb36", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7", "size": 48693, "upload_time": "2019-06-17T12:05:41", "url": "https://files.pythonhosted.org/packages/55/78/d1faab4d2983579a053ced5d0ded5df29766169dc7b33a91f12fa1d85ef8/json2python-models-0.1.2.tar.gz" } ] }