| Name | jmesflat JSON |
| Version |
0.0.2
JSON |
| download |
| home_page | None |
| Summary | Initialize jmesflat package |
| upload_time | 2024-08-26 02:16:52 |
| maintainer | None |
| docs_url | None |
| author | None |
| requires_python | >=3.10 |
| license | None |
| keywords |
|
| VCS |
 |
| bugtrack_url |
|
| requirements |
No requirements were recorded.
|
| Travis-CI |
No Travis.
|
| coveralls test coverage |
No coveralls.
|
# jmesflat
Built upon and considered an extension of [`jmespath`](https://jmespath.org), `jmesflat` is similarly pronounced (say "James flat") and provides a simple interface for flattening, 'unflattening', and merging deeply nested json objects.
Common use cases:
```python
>>> # 1. Building deeply nested objects without constructing individual layers:
>>> import jmesflat as jf
>>> nest1 = jf.unflatten({"a.b[0].c[0].d": "e", "a.b[1].f": "g"})
>>> nest1
{'a': {'b': [{'c': [{'d': 'e'}]}, {'f': 'g'}]}}
>>>
>>> # 2. Merging deeply nested objects:
>>> nest2 = {"a": {"b": [{"f": "g"}, {"c": [{"d": "e"}]}]}}
>>> merged_nest = jf.merge(nest1, nest2)
>>> merged_nest
{'a': {'b': [{'c': [{'d': 'e'}], 'f': 'g'}, {'c': [{'d': 'e'}], 'f': 'g'}]}}
>>>
>>> # 3. Making dumps of complex nest objects compact and human readable
>>> import json
>>> print(json.dumps(jf.flatten(merged_nest), indent=2))
{
"a.b[0].c[0].d": "e",
"a.b[0].f": "g",
"a.b[1].c[0].d": "e",
"a.b[1].f": "g"
}
```
## Installation
`pip install jmesflat`
## Compatibility
Python 3.9 or greater
## Basic Features Demo
1. Keys *can* contain spaces and reserved characters (`@` and `-`)
2. Supports any arbitrary nesting pattern including mixed and multi-level array objects
3. Empty lists / dicts are considered atomic types and included in the flattened output alongside the 'true' atomic types `int`, `float`, `str`, `bool`, and `None`
4. Flatten / unflatten / merge at an arbitrary *object* depth using the `level` parameter (depth *cannot exceed* the depth of the first array instance)
5. Extend rather than overwrite arrays during merge operations using the `array_merge` parameter. 'topdown' merges extend at the first array instance. 'bottomup' extends at the final array instance.
6. Scrub the data during `flatten`/`unflatten`/`merge` operations or simply scrub a nested object via `clean` using the `discard_check` parameter. The check is ONLY applied to `nest2` during the `merge` operation.
```python
>>> import json
>>> import jmesflat as jf
>>>
>>> test_nest = {
... "Outer Object Key 1": {
... "mixedArray": [
... "mixed array string",
... {"mixed Array Object 1 Key": "spaces demo"},
... 12345,
... [
... {"@subArray": "@ symbol demo"},
... {"@subArray": 1.2345},
... {"@subArray": None},
... ],
... {"mixed-array-object-2-key": "dashed key demo"},
... [],
... {},
... ],
... },
... "Outer Object Key 2": {
... "deepNest": {
... "a": [
... {"b": 1},
... {
... "c": {
... "d": [
... {"e": "f", "g": "h"},
... {"e": "f1"}
... ]
... }
... }
... ]
... },
... },
... }
>>>
>>> flat = jf.flatten(test_nest, level=1)
>>> print(json.dumps(flat, indent=2))
{
"Outer Object Key 1": {
"mixedArray[0]": "mixed array string",
"mixedArray[1].mixed Array Object 1 Key": "spaces demo",
"mixedArray[2]": 12345,
"mixedArray[3][0].@subArray": "@ symbol demo",
"mixedArray[3][1].@subArray": "@ symbol demo",
"mixedArray[3][2].@subArray": "@ symbol demo",
"mixedArray[4].mixed-array-object-2-key": "dashed key demo",
"mixedArray[5]": [],
"mixedArray[6]": {}
},
"Outer Object Key 2": {
"deepNest.a[0].b": 1,
"deepNest.a[1].c.d[0].e": "f",
"deepNest.a[1].c.d[0].g": "h",
"deepNest.a[1].c.d[1].e": "f1"
}
}
>>>
>>> jf.unflatten(flat, level=1) == test_nest
True
>>>
>>> from copy import deepcopy
>>> test_nest2 = deepcopy(test_nest)
>>> # NOTE: `jf.flatten` wrapper is used for ease of visualization only in the merge/clean examples below
>>> print(json.dumps(jf.flatten(jf.merge(test_nest, test_nest2, level=1), level=2), indent=2))
{
"Outer Object Key 1": {
"mixedArray": {
"[0]": "mixed array string",
"[1].mixed Array Object 1 Key": "spaces demo",
"[2]": 12345,
"[3][0].@subArray": "@ symbol demo",
"[3][1].@subArray": 1.2345,
"[3][2].@subArray": null,
"[4].mixed-array-object-2-key": "dashed key demo",
"[5]": [],
"[6]": {}
}
},
"Outer Object Key 2": {
"deepNest": {
"a[0].b": 1,
"a[1].c.d[0].e": "f",
"a[1].c.d[0].g": "h",
"a[1].c.d[1].e": "f1"
}
}
}
>>> print(json.dumps(jf.flatten(jf.merge(test_nest, test_nest2, level=1, array_merge="topdown"), level=2), indent=2))
{
"Outer Object Key 1": {
"mixedArray": {
"[0]": "mixed array string",
"[1].mixed Array Object 1 Key": "spaces demo",
"[2]": 12345,
"[3][0].@subArray": "@ symbol demo",
"[3][1].@subArray": 1.2345,
"[3][2].@subArray": null,
"[4].mixed-array-object-2-key": "dashed key demo",
"[5]": [],
"[6]": {},
"[7]": "mixed array string",
"[8].mixed Array Object 1 Key": "spaces demo",
"[9]": 12345,
"[10][0].@subArray": "@ symbol demo",
"[10][1].@subArray": 1.2345,
"[10][2].@subArray": null,
"[11].mixed-array-object-2-key": "dashed key demo",
"[12]": [],
"[13]": {}
}
},
"Outer Object Key 2": {
"deepNest": {
"a[0].b": 1,
"a[1].c.d[0].e": "f",
"a[1].c.d[0].g": "h",
"a[1].c.d[1].e": "f1",
"a[2].b": 1,
"a[3].c.d[0].e": "f",
"a[3].c.d[0].g": "h",
"a[3].c.d[1].e": "f1"
}
}
}
>>> print(json.dumps(jf.flatten(jf.merge(test_nest, test_nest2, level=1, array_merge="bottomup"), level=2), indent=2))
{
"Outer Object Key 1": {
"mixedArray": {
"[0]": "mixed array string",
"[1].mixed Array Object 1 Key": "spaces demo",
"[2]": 12345,
"[3][0].@subArray": "@ symbol demo",
"[3][1].@subArray": 1.2345,
"[3][2].@subArray": null,
"[3][3].@subArray": "@ symbol demo",
"[3][4].@subArray": 1.2345,
"[3][5].@subArray": null,
"[4].mixed-array-object-2-key": "dashed key demo",
"[5]": [],
"[6]": {},
"[7]": "mixed array string",
"[8].mixed Array Object 1 Key": "spaces demo",
"[9]": 12345,
"[10].mixed-array-object-2-key": "dashed key demo",
"[11]": [],
"[12]": {}
}
},
"Outer Object Key 2": {
"deepNest": {
"a[0].b": 1,
"a[1].c.d[0].e": "f",
"a[1].c.d[0].g": "h",
"a[1].c.d[1].e": "f1",
"a[1].c.d[2].e": "f",
"a[1].c.d[2].g": "h",
"a[1].c.d[3].e": "f1",
"a[2].b": 1
}
}
}
>>> print(json.dumps(jf.flatten(jf.clean(test_nest, discard_check=lambda key, val: "-" in key or not isinstance(val, (str, int))), level=2), indent=2))
{
"Outer Object Key 1": {
"mixedArray": {
"[0]": "mixed array string",
"[1].mixed Array Object 1 Key": "spaces demo",
"[2]": 12345,
"[3][0].@subArray": "@ symbol demo"
}
},
"Outer Object Key 2": {
"deepNest": {
"a[0].b": 1,
"a[1].c.d[0].e": "f",
"a[1].c.d[0].g": "h",
"a[1].c.d[1].e": "f1"
}
}
}
```
## The `constants` Module
The `constants` module allows global defaults to be set for several key features. For example, a global discard check function can be defined by setting the value of `jf.constants.DISCARD_CHECK`. If the user wishes to discard all `None` type values, simply set `jf.constants.DISCARD_CHECK = lambda _, val: val is None` after the initial `import jmesflat as jf` statement. In addition, users can customize the default values that will be used when extending arrays during an index preserving unflatten operation via `jf.MISSING_ARRAY_ENTRY_VALUE`, a callable that accepts the flattened key of the array element *being set* and the value said *is being set to* and returns the value that should be used to pad the array until its length is >= the desired index. Other settings in the `constants` module are considered 'use at your own risk' and included for possible future extensibility.
Raw data
{
"_id": null,
"home_page": null,
"name": "jmesflat",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": null,
"keywords": null,
"author": null,
"author_email": "Sam Hartzog <sam.hartzog@hank.ai>",
"download_url": "https://files.pythonhosted.org/packages/40/62/48cde36b900c43f735240c10fb0b81eaf2baa62ab737c7e70cc9e5cd1364/jmesflat-0.0.2.tar.gz",
"platform": null,
"description": "# jmesflat\n\nBuilt upon and considered an extension of [`jmespath`](https://jmespath.org), `jmesflat` is similarly pronounced (say \"James flat\") and provides a simple interface for flattening, 'unflattening', and merging deeply nested json objects.\n\nCommon use cases:\n\n```python\n>>> # 1. Building deeply nested objects without constructing individual layers:\n>>> import jmesflat as jf\n>>> nest1 = jf.unflatten({\"a.b[0].c[0].d\": \"e\", \"a.b[1].f\": \"g\"})\n>>> nest1\n{'a': {'b': [{'c': [{'d': 'e'}]}, {'f': 'g'}]}}\n>>>\n>>> # 2. Merging deeply nested objects:\n>>> nest2 = {\"a\": {\"b\": [{\"f\": \"g\"}, {\"c\": [{\"d\": \"e\"}]}]}}\n>>> merged_nest = jf.merge(nest1, nest2)\n>>> merged_nest\n{'a': {'b': [{'c': [{'d': 'e'}], 'f': 'g'}, {'c': [{'d': 'e'}], 'f': 'g'}]}}\n>>>\n>>> # 3. Making dumps of complex nest objects compact and human readable\n>>> import json\n>>> print(json.dumps(jf.flatten(merged_nest), indent=2))\n{\n \"a.b[0].c[0].d\": \"e\",\n \"a.b[0].f\": \"g\",\n \"a.b[1].c[0].d\": \"e\",\n \"a.b[1].f\": \"g\"\n}\n```\n\n## Installation\n\n`pip install jmesflat`\n\n## Compatibility\n\nPython 3.9 or greater\n\n## Basic Features Demo\n\n1. Keys *can* contain spaces and reserved characters (`@` and `-`)\n2. Supports any arbitrary nesting pattern including mixed and multi-level array objects\n3. Empty lists / dicts are considered atomic types and included in the flattened output alongside the 'true' atomic types `int`, `float`, `str`, `bool`, and `None`\n4. Flatten / unflatten / merge at an arbitrary *object* depth using the `level` parameter (depth *cannot exceed* the depth of the first array instance)\n5. Extend rather than overwrite arrays during merge operations using the `array_merge` parameter. 'topdown' merges extend at the first array instance. 'bottomup' extends at the final array instance.\n6. Scrub the data during `flatten`/`unflatten`/`merge` operations or simply scrub a nested object via `clean` using the `discard_check` parameter. The check is ONLY applied to `nest2` during the `merge` operation.\n\n```python\n>>> import json\n>>> import jmesflat as jf\n>>>\n>>> test_nest = {\n... \"Outer Object Key 1\": {\n... \"mixedArray\": [\n... \"mixed array string\",\n... {\"mixed Array Object 1 Key\": \"spaces demo\"},\n... 12345,\n... [\n... {\"@subArray\": \"@ symbol demo\"},\n... {\"@subArray\": 1.2345},\n... {\"@subArray\": None},\n... ],\n... {\"mixed-array-object-2-key\": \"dashed key demo\"},\n... [],\n... {},\n... ],\n... },\n... \"Outer Object Key 2\": {\n... \"deepNest\": {\n... \"a\": [\n... {\"b\": 1},\n... {\n... \"c\": {\n... \"d\": [\n... {\"e\": \"f\", \"g\": \"h\"},\n... {\"e\": \"f1\"}\n... ]\n... }\n... }\n... ]\n... },\n... },\n... }\n>>>\n>>> flat = jf.flatten(test_nest, level=1)\n>>> print(json.dumps(flat, indent=2))\n{\n \"Outer Object Key 1\": {\n \"mixedArray[0]\": \"mixed array string\",\n \"mixedArray[1].mixed Array Object 1 Key\": \"spaces demo\",\n \"mixedArray[2]\": 12345,\n \"mixedArray[3][0].@subArray\": \"@ symbol demo\",\n \"mixedArray[3][1].@subArray\": \"@ symbol demo\",\n \"mixedArray[3][2].@subArray\": \"@ symbol demo\",\n \"mixedArray[4].mixed-array-object-2-key\": \"dashed key demo\",\n \"mixedArray[5]\": [],\n \"mixedArray[6]\": {}\n },\n \"Outer Object Key 2\": {\n \"deepNest.a[0].b\": 1,\n \"deepNest.a[1].c.d[0].e\": \"f\",\n \"deepNest.a[1].c.d[0].g\": \"h\",\n \"deepNest.a[1].c.d[1].e\": \"f1\"\n }\n}\n>>>\n>>> jf.unflatten(flat, level=1) == test_nest\nTrue\n>>>\n>>> from copy import deepcopy\n>>> test_nest2 = deepcopy(test_nest)\n>>> # NOTE: `jf.flatten` wrapper is used for ease of visualization only in the merge/clean examples below\n>>> print(json.dumps(jf.flatten(jf.merge(test_nest, test_nest2, level=1), level=2), indent=2))\n{\n \"Outer Object Key 1\": {\n \"mixedArray\": {\n \"[0]\": \"mixed array string\",\n \"[1].mixed Array Object 1 Key\": \"spaces demo\",\n \"[2]\": 12345,\n \"[3][0].@subArray\": \"@ symbol demo\",\n \"[3][1].@subArray\": 1.2345,\n \"[3][2].@subArray\": null,\n \"[4].mixed-array-object-2-key\": \"dashed key demo\",\n \"[5]\": [],\n \"[6]\": {}\n }\n },\n \"Outer Object Key 2\": {\n \"deepNest\": {\n \"a[0].b\": 1,\n \"a[1].c.d[0].e\": \"f\",\n \"a[1].c.d[0].g\": \"h\",\n \"a[1].c.d[1].e\": \"f1\"\n }\n }\n}\n>>> print(json.dumps(jf.flatten(jf.merge(test_nest, test_nest2, level=1, array_merge=\"topdown\"), level=2), indent=2))\n{\n \"Outer Object Key 1\": {\n \"mixedArray\": {\n \"[0]\": \"mixed array string\",\n \"[1].mixed Array Object 1 Key\": \"spaces demo\",\n \"[2]\": 12345,\n \"[3][0].@subArray\": \"@ symbol demo\",\n \"[3][1].@subArray\": 1.2345,\n \"[3][2].@subArray\": null,\n \"[4].mixed-array-object-2-key\": \"dashed key demo\",\n \"[5]\": [],\n \"[6]\": {},\n \"[7]\": \"mixed array string\",\n \"[8].mixed Array Object 1 Key\": \"spaces demo\",\n \"[9]\": 12345,\n \"[10][0].@subArray\": \"@ symbol demo\",\n \"[10][1].@subArray\": 1.2345,\n \"[10][2].@subArray\": null,\n \"[11].mixed-array-object-2-key\": \"dashed key demo\",\n \"[12]\": [],\n \"[13]\": {}\n }\n },\n \"Outer Object Key 2\": {\n \"deepNest\": {\n \"a[0].b\": 1,\n \"a[1].c.d[0].e\": \"f\",\n \"a[1].c.d[0].g\": \"h\",\n \"a[1].c.d[1].e\": \"f1\",\n \"a[2].b\": 1,\n \"a[3].c.d[0].e\": \"f\",\n \"a[3].c.d[0].g\": \"h\",\n \"a[3].c.d[1].e\": \"f1\"\n }\n }\n}\n>>> print(json.dumps(jf.flatten(jf.merge(test_nest, test_nest2, level=1, array_merge=\"bottomup\"), level=2), indent=2))\n{\n \"Outer Object Key 1\": {\n \"mixedArray\": {\n \"[0]\": \"mixed array string\",\n \"[1].mixed Array Object 1 Key\": \"spaces demo\",\n \"[2]\": 12345,\n \"[3][0].@subArray\": \"@ symbol demo\",\n \"[3][1].@subArray\": 1.2345,\n \"[3][2].@subArray\": null,\n \"[3][3].@subArray\": \"@ symbol demo\",\n \"[3][4].@subArray\": 1.2345,\n \"[3][5].@subArray\": null,\n \"[4].mixed-array-object-2-key\": \"dashed key demo\",\n \"[5]\": [],\n \"[6]\": {},\n \"[7]\": \"mixed array string\",\n \"[8].mixed Array Object 1 Key\": \"spaces demo\",\n \"[9]\": 12345,\n \"[10].mixed-array-object-2-key\": \"dashed key demo\",\n \"[11]\": [],\n \"[12]\": {}\n }\n },\n \"Outer Object Key 2\": {\n \"deepNest\": {\n \"a[0].b\": 1,\n \"a[1].c.d[0].e\": \"f\",\n \"a[1].c.d[0].g\": \"h\",\n \"a[1].c.d[1].e\": \"f1\",\n \"a[1].c.d[2].e\": \"f\",\n \"a[1].c.d[2].g\": \"h\",\n \"a[1].c.d[3].e\": \"f1\",\n \"a[2].b\": 1\n }\n }\n}\n>>> print(json.dumps(jf.flatten(jf.clean(test_nest, discard_check=lambda key, val: \"-\" in key or not isinstance(val, (str, int))), level=2), indent=2))\n{\n \"Outer Object Key 1\": {\n \"mixedArray\": {\n \"[0]\": \"mixed array string\",\n \"[1].mixed Array Object 1 Key\": \"spaces demo\",\n \"[2]\": 12345,\n \"[3][0].@subArray\": \"@ symbol demo\"\n }\n },\n \"Outer Object Key 2\": {\n \"deepNest\": {\n \"a[0].b\": 1,\n \"a[1].c.d[0].e\": \"f\",\n \"a[1].c.d[0].g\": \"h\",\n \"a[1].c.d[1].e\": \"f1\"\n }\n }\n}\n```\n\n## The `constants` Module\n\nThe `constants` module allows global defaults to be set for several key features. For example, a global discard check function can be defined by setting the value of `jf.constants.DISCARD_CHECK`. If the user wishes to discard all `None` type values, simply set `jf.constants.DISCARD_CHECK = lambda _, val: val is None` after the initial `import jmesflat as jf` statement. In addition, users can customize the default values that will be used when extending arrays during an index preserving unflatten operation via `jf.MISSING_ARRAY_ENTRY_VALUE`, a callable that accepts the flattened key of the array element *being set* and the value said *is being set to* and returns the value that should be used to pad the array until its length is >= the desired index. Other settings in the `constants` module are considered 'use at your own risk' and included for possible future extensibility.\n",
"bugtrack_url": null,
"license": null,
"summary": "Initialize jmesflat package",
"version": "0.0.2",
"project_urls": {
"Home": "https://github.com/hank-ai/jmesflat",
"Issues": "https://github.com/hank-ai/jmesflat/issues"
},
"split_keywords": [],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "456576aed320a7b019776cb7a9b3648619fe38d7f8867f0d6ad04bca46fe88d2",
"md5": "4fd603881fdee939db37488054add5d3",
"sha256": "933e95ae45f75767b981421e0b62cac94b4b5c383d1a6ba9b3ff5b041b61eb4e"
},
"downloads": -1,
"filename": "jmesflat-0.0.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "4fd603881fdee939db37488054add5d3",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 11674,
"upload_time": "2024-08-26T02:16:50",
"upload_time_iso_8601": "2024-08-26T02:16:50.634661Z",
"url": "https://files.pythonhosted.org/packages/45/65/76aed320a7b019776cb7a9b3648619fe38d7f8867f0d6ad04bca46fe88d2/jmesflat-0.0.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "406248cde36b900c43f735240c10fb0b81eaf2baa62ab737c7e70cc9e5cd1364",
"md5": "f7394d21d5fe77e5a9cc2119a656d574",
"sha256": "10297dc5060501ff50b1b18d1b4a1e8b522b7c8b29f9cdd6c027be5f2f68fdfc"
},
"downloads": -1,
"filename": "jmesflat-0.0.2.tar.gz",
"has_sig": false,
"md5_digest": "f7394d21d5fe77e5a9cc2119a656d574",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 14386,
"upload_time": "2024-08-26T02:16:52",
"upload_time_iso_8601": "2024-08-26T02:16:52.100403Z",
"url": "https://files.pythonhosted.org/packages/40/62/48cde36b900c43f735240c10fb0b81eaf2baa62ab737c7e70cc9e5cd1364/jmesflat-0.0.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-08-26 02:16:52",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "hank-ai",
"github_project": "jmesflat",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [],
"lcname": "jmesflat"
}