{"id":13468489,"url":"https://github.com/fabiocaccamo/python-benedict","last_synced_at":"2025-05-13T18:16:52.617Z","repository":{"id":37773920,"uuid":"187202744","full_name":"fabiocaccamo/python-benedict","owner":"fabiocaccamo","description":":blue_book: dict subclass with keylist/keypath support, built-in I/O operations (base64, csv, html, ini, json, pickle, plist, query-string, toml, xls, xml, yaml), s3 support and many utilities.","archived":false,"fork":false,"pushed_at":"2025-05-05T16:58:35.000Z","size":5578,"stargazers_count":1564,"open_issues_count":25,"forks_count":46,"subscribers_count":12,"default_branch":"main","last_synced_at":"2025-05-05T18:04:01.672Z","etag":null,"topics":["base64","csv","decode","dict","dictionary","encode","filter","flatten","json","keypath","pickle","plist","python","query-string","subset","toml","traverse","xls","xml","yaml"],"latest_commit_sha":null,"homepage":"","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/fabiocaccamo.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["fabiocaccamo"],"polar":"fabiocaccamo","ko_fi":"fabiocaccamo","liberapay":"fabiocaccamo","tidelift":"pypi/python-benedict","custom":["https://www.buymeacoffee.com/fabiocaccamo","https://www.paypal.me/fabiocaccamo"]}},"created_at":"2019-05-17T11:13:40.000Z","updated_at":"2025-05-04T21:51:20.000Z","dependencies_parsed_at":"2022-07-08T02:10:46.873Z","dependency_job_id":"36a45f05-47b5-4ead-a021-450367fee457","html_url":"https://github.com/fabiocaccamo/python-benedict","commit_stats":{"total_commits":846,"total_committers":7,"mean_commits":"120.85714285714286","dds":"0.25886524822695034","last_synced_commit":"b878e0d4d7d8095a87302957098b058207a853dc"},"previous_names":[],"tags_count":67,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fabiocaccamo%2Fpython-benedict","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fabiocaccamo%2Fpython-benedict/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fabiocaccamo%2Fpython-benedict/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fabiocaccamo%2Fpython-benedict/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fabiocaccamo","download_url":"https://codeload.github.com/fabiocaccamo/python-benedict/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254000893,"owners_count":21997444,"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":["base64","csv","decode","dict","dictionary","encode","filter","flatten","json","keypath","pickle","plist","python","query-string","subset","toml","traverse","xls","xml","yaml"],"created_at":"2024-07-31T15:01:12.089Z","updated_at":"2025-05-13T18:16:52.537Z","avatar_url":"https://github.com/fabiocaccamo.png","language":"Python","readme":"[![](https://img.shields.io/pypi/pyversions/python-benedict.svg?color=blue\u0026logo=python\u0026logoColor=white)](https://www.python.org/)\n[![](https://img.shields.io/pypi/v/python-benedict.svg?color=blue\u0026logo=pypi\u0026logoColor=white)](https://pypi.org/project/python-benedict/)\n[![](https://static.pepy.tech/badge/python-benedict/month)](https://pepy.tech/project/python-benedict)\n[![](https://img.shields.io/github/stars/fabiocaccamo/python-benedict?logo=github\u0026style=flat)](https://github.com/fabiocaccamo/python-benedict/stargazers)\n[![](https://img.shields.io/pypi/l/python-benedict.svg?color=blue)](https://github.com/fabiocaccamo/python-benedict/blob/main/LICENSE.txt)\n\n[![](https://results.pre-commit.ci/badge/github/fabiocaccamo/python-benedict/main.svg)](https://results.pre-commit.ci/latest/github/fabiocaccamo/python-benedict/main)\n[![](https://img.shields.io/github/actions/workflow/status/fabiocaccamo/python-benedict/test-package.yml?branch=main\u0026label=build\u0026logo=github)](https://github.com/fabiocaccamo/python-benedict)\n[![](https://img.shields.io/codecov/c/gh/fabiocaccamo/python-benedict?logo=codecov)](https://codecov.io/gh/fabiocaccamo/python-benedict)\n[![](https://img.shields.io/codeclimate/maintainability/fabiocaccamo/python-benedict?logo=code-climate)](https://codeclimate.com/github/fabiocaccamo/python-benedict/)\n[![](https://img.shields.io/codacy/grade/0dbd5cc2089f4dce80a0e49e6822be3c?logo=codacy)](https://www.codacy.com/app/fabiocaccamo/python-benedict)\n[![](https://img.shields.io/scrutinizer/quality/g/fabiocaccamo/python-benedict?logo=scrutinizer)](https://scrutinizer-ci.com/g/fabiocaccamo/python-benedict/?branch=main)\n[![](https://img.shields.io/badge/code%20style-black-000000.svg?logo=python\u0026logoColor=black)](https://github.com/psf/black)\n[![](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)\n\n# python-benedict\npython-benedict is a dict subclass with **keylist/keypath/keyattr** support, **I/O** shortcuts (`base64`, `cli`, `csv`, `html`, `ini`, `json`, `pickle`, `plist`, `query-string`, `toml`, `xls`, `xml`, `yaml`) and many **utilities**... for humans, obviously.\n\n## Features\n-   100% **backward-compatible**, you can safely wrap existing dictionaries.\n-   `NEW` **Keyattr** support for get/set items using **keys as attributes**.\n-   **Keylist** support using **list of keys** as key.\n-   **Keypath** support using **keypath-separator** *(dot syntax by default)*.\n-   Keypath **list-index** support  *(also negative)* using the standard `[n]` suffix.\n-   Normalized **I/O operations** with most common formats: `base64`, `cli`, `csv`, `html`, `ini`, `json`, `pickle`, `plist`, `query-string`, `toml`, `xls`, `xml`, `yaml`.\n-   Multiple **I/O operations** backends: `file-system` *(read/write)*, `url` *(read-only)*, `s3` *(read/write)*.\n-   Many **utility** and **parse methods** to retrieve data as needed *(check the [API](#api) section)*.\n-   Well **tested**. ;)\n\n## Index\n-   [Installation](#installation)\n    -   [Optional Requirements](#optional-requirements)\n-   [Usage](#usage)\n    -   [Basics](#basics)\n    -   [Keyattr](#keyattr) `my_dict.x.y.z`\n    -   [Keylist](#keylist) `my_dict[[\"x\", \"y\", \"z\"]]`\n    -   [Keypath](#keypath) `my_dict[\"x.y.z\"]`\n        -   [Custom keypath separator](#custom-keypath-separator)\n        -   [Change keypath separator](#change-keypath-separator)\n        -   [Disable keypath functionality](#disable-keypath-functionality)\n        -   [List index support](#list-index-support)\n    -   [I/O](#io)\n    -   [API](#api)\n        -   [Utility methods](#utility-methods)\n        -   [I/O methods](#io-methods)\n        -   [Parse methods](#parse-methods)\n-   [Testing](#testing)\n-   [License](#license)\n\n## Installation\nIf you want to install **everything**:\n-   Run `pip install \"python-benedict[all]\"`\n\nalternatively you can install the main package:\n-   Run `pip install python-benedict`, then install only the [optional requirements](#optional-requirements) you need.\n\n### Optional Requirements\nHere the hierarchy of possible installation targets available when running `pip install \"python-benedict[...]\"` *(each target installs all its sub-targets)*:\n- `[all]`\n    - `[io]`\n        - `[html]`\n        - `[toml]`\n        - `[xls]`\n        - `[xml]`\n        - `[yaml]`\n    - `[parse]`\n    - `[s3]`\n\n## Usage\n\n### Basics\n`benedict` is a `dict` subclass, so it is possible to use it as a normal dictionary *(you can just cast an existing dict)*.\n\n```python\nfrom benedict import benedict\n\n# create a new empty instance\nd = benedict()\n\n# or cast an existing dict\nd = benedict(existing_dict)\n\n# or create from data source (filepath, url or data-string) in a supported format:\n# Base64, CSV, JSON, TOML, XML, YAML, query-string\nd = benedict(\"https://localhost:8000/data.json\", format=\"json\")\n\n# or in a Django view\nparams = benedict(request.GET.items())\npage = params.get_int(\"page\", 1)\n```\n\n### Keyattr\nIt is possible to get/set items using **keys as attributes** (dotted notation).\n\n```python\nd = benedict(keyattr_dynamic=True) # default False\nd.profile.firstname = \"Fabio\"\nd.profile.lastname = \"Caccamo\"\nprint(d) # -\u003e { \"profile\":{ \"firstname\":\"Fabio\", \"lastname\":\"Caccamo\" } }\n```\n\nBy default, if the `keyattr_dynamic` is not explicitly set to `True`, this functionality works for get/set only already existing items.\n\n#### Disable keyattr functionality\nYou can disable the keyattr functionality passing `keyattr_enabled=False` option in the constructor.\n\n```python\nd = benedict(existing_dict, keyattr_enabled=False) # default True\n```\n\nor using the `getter/setter` property.\n\n```python\nd.keyattr_enabled = False\n```\n\n#### Dynamic keyattr functionality\nYou can enable the dynamic attributes access functionality passing `keyattr_dynamic=True` in the constructor.\n\n```python\nd = benedict(existing_dict, keyattr_dynamic=True) # default False\n```\n\nor using the `getter/setter` property.\n\n```python\nd.keyattr_dynamic = True\n```\n\n\u003e **Warning** - even if this feature is very useful, it has some obvious limitations: it works only for string keys that are *unprotected* (not starting with an `_`) and that don't clash with the currently supported methods names.\n\n### Keylist\nWherever a **key** is used, it is possible to use also a **list of keys**.\n\n```python\nd = benedict()\n\n# set values by keys list\nd[[\"profile\", \"firstname\"]] = \"Fabio\"\nd[[\"profile\", \"lastname\"]] = \"Caccamo\"\nprint(d) # -\u003e { \"profile\":{ \"firstname\":\"Fabio\", \"lastname\":\"Caccamo\" } }\nprint(d[\"profile\"]) # -\u003e { \"firstname\":\"Fabio\", \"lastname\":\"Caccamo\" }\n\n# check if keypath exists in dict\nprint([[\"profile\", \"lastname\"]] in d) # -\u003e True\n\n# delete value by keys list\ndel d[[\"profile\", \"lastname\"]]\nprint(d[\"profile\"]) # -\u003e { \"firstname\":\"Fabio\" }\n```\n\n### Keypath\n`.` is the default keypath separator.\n\nIf you cast an existing dict and its keys contain the keypath separator a `ValueError` will be raised.\n\nIn this case you should use a [custom keypath separator](#custom-keypath-separator) or [disable keypath functionality](#disable-keypath-functionality).\n\n```python\nd = benedict()\n\n# set values by keypath\nd[\"profile.firstname\"] = \"Fabio\"\nd[\"profile.lastname\"] = \"Caccamo\"\nprint(d) # -\u003e { \"profile\":{ \"firstname\":\"Fabio\", \"lastname\":\"Caccamo\" } }\nprint(d[\"profile\"]) # -\u003e { \"firstname\":\"Fabio\", \"lastname\":\"Caccamo\" }\n\n# check if keypath exists in dict\nprint(\"profile.lastname\" in d) # -\u003e True\n\n# delete value by keypath\ndel d[\"profile.lastname\"]\n```\n\n#### Custom keypath separator\nYou can customize the keypath separator passing the `keypath_separator` argument in the constructor.\n\nIf you pass an existing dict to the constructor and its keys contain the keypath separator an `Exception` will be raised.\n\n```python\nd = benedict(existing_dict, keypath_separator=\"/\")\n```\n\n#### Change keypath separator\nYou can change the `keypath_separator` at any time using the `getter/setter` property.\n\nIf any existing key contains the new `keypath_separator` an `Exception` will be raised.\n\n```python\nd.keypath_separator = \"/\"\n```\n\n#### Disable keypath functionality\nYou can disable the keypath functionality passing `keypath_separator=None` option in the constructor.\n\n```python\nd = benedict(existing_dict, keypath_separator=None)\n```\n\nor using the `getter/setter` property.\n\n```python\nd.keypath_separator = None\n```\n\n#### List index support\nList index are supported, keypaths can include indexes *(also negative)* using `[n]`, to perform any operation very fast:\n\n```python\n# Eg. get last location cordinates of the first result:\nloc = d[\"results[0].locations[-1].coordinates\"]\nlat = loc.get_decimal(\"latitude\")\nlng = loc.get_decimal(\"longitude\")\n```\n\n### I/O\n\nFor simplifying I/O operations, `benedict` supports a variety of input/output methods with most common formats: `base64`, `cli`, `csv`, `html`, `ini`, `json`, `pickle`, `plist`, `query-string`, `toml`, `xls`, `xml`, `yaml`.\n\n#### Input via constructor\n\nIt is possible to create a `benedict` instance directly from data-source (`filepath`, `url`, `s3` or `data` string) by passing the data source and the data format (optional, default \"json\") in the constructor.\n\n```python\n# filepath\nd = benedict(\"/root/data.yml\", format=\"yaml\")\n\n# url\nd = benedict(\"https://localhost:8000/data.xml\", format=\"xml\")\n\n# s3\nd = benedict(\"s3://my-bucket/data.xml\", s3_options={\"aws_access_key_id\": \"...\", \"aws_secret_access_key\": \"...\"})\n\n# data\nd = benedict('{\"a\": 1, \"b\": 2, \"c\": 3, \"x\": 7, \"y\": 8, \"z\": 9}')\n```\n\n#### Input methods\n\n- All *input* methods can be accessed as class methods and are prefixed by `from_*` followed by the format name.\n- In all *input* methods, the first argument can represent a source: **file** path, **url**, **s3** url, or **data** string.\n\n#### Input sources\n\nAll supported sources (**file**, **url**, **s3**, **data**) are allowed by default, but in certains situations when the input data comes from **untrusted sources** it may be useful to restrict the allowed sources using the `sources` argument:\n\n```python\n# url\nd = benedict(\"https://localhost:8000/data.json\", sources=[\"url\"]) # -\u003e ok\nd = benedict.from_json(\"https://localhost:8000/data.json\", sources=[\"url\"]) # -\u003e ok\n\n# s3\nd = benedict(\"s3://my-bucket/data.json\", sources=[\"url\"]) # -\u003e raise ValueError\nd = benedict.from_json(\"s3://my-bucket/data.json\", sources=[\"url\"]) # -\u003e raise ValueError\n```\n\n#### Output methods\n\n- All *output* methods can be accessed as instance methods and are prefixed by `to_*` followed by the format name.\n- In all *output* methods, if `filepath=\"...\"` kwarg is specified, the output will be also **saved** at the specified filepath.\n\n#### Supported formats\n\nHere are the details of the supported formats, operations and extra options docs.\n\n| **format**     | **input**          | **output**         | **extra options docs**                                                                |\n|----------------|--------------------|--------------------|---------------------------------------------------------------------------------------|\n| `base64`       | :white_check_mark: | :white_check_mark: | -                                                                                     |\n| `cli`          | :white_check_mark: | :x:                | [argparse](https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser)   |\n| `csv`          | :white_check_mark: | :white_check_mark: | [csv](https://docs.python.org/3/library/csv.html)                                     |\n| `html`         | :white_check_mark: | :x:                | [bs4](https://beautiful-soup-4.readthedocs.io) *(Beautiful Soup 4)*                   |\n| `ini`          | :white_check_mark: | :white_check_mark: | [configparser](https://docs.python.org/3/library/configparser.html)                   |\n| `json`         | :white_check_mark: | :white_check_mark: | [json](https://docs.python.org/3/library/json.html)                                   |\n| `pickle`       | :white_check_mark: | :white_check_mark: | [pickle](https://docs.python.org/3/library/pickle.html)                               |\n| `plist`        | :white_check_mark: | :white_check_mark: | [plistlib](https://docs.python.org/3/library/plistlib.html)                           |\n| `query-string` | :white_check_mark: | :white_check_mark: | -                                                                                     |\n| `toml`         | :white_check_mark: | :white_check_mark: | [toml](https://pypi.org/project/toml/)                                                |\n| `xls`          | :white_check_mark: | :x:                | [openpyxl](https://openpyxl.readthedocs.io/) - [xlrd](https://pypi.org/project/xlrd/) |\n| `xml`          | :white_check_mark: | :white_check_mark: | [xmltodict](https://github.com/martinblech/xmltodict)                                 |\n| `yaml`         | :white_check_mark: | :white_check_mark: | [PyYAML](https://pyyaml.org/wiki/PyYAMLDocumentation)                                 |\n\n### API\n\n-   **Utility methods**\n\n    -   [`clean`](#clean)\n    -   [`clone`](#clone)\n    -   [`dump`](#dump)\n    -   [`filter`](#filter)\n    -   [`find`](#find)\n    -   [`flatten`](#flatten)\n    -   [`groupby`](#groupby)\n    -   [`invert`](#invert)\n    -   [`items_sorted_by_keys`](#items_sorted_by_keys)\n    -   [`items_sorted_by_values`](#items_sorted_by_values)\n    -   [`keypaths`](#keypaths)\n    -   [`match`](#match)\n    -   [`merge`](#merge)\n    -   [`move`](#move)\n    -   [`nest`](#nest)\n    -   [`remove`](#remove)\n    -   [`rename`](#rename)\n    -   [`search`](#search)\n    -   [`standardize`](#standardize)\n    -   [`subset`](#subset)\n    -   [`swap`](#swap)\n    -   [`traverse`](#traverse)\n    -   [`unflatten`](#unflatten)\n    -   [`unique`](#unique)\n\n-   **I/O methods**\n\n    -   [`from_base64`](#from_base64)\n    -   [`from_cli`](#from_cli)\n    -   [`from_csv`](#from_csv)\n    -   [`from_ini`](#from_ini)\n    -   [`from_html`](#from_html)\n    -   [`from_json`](#from_json)\n    -   [`from_pickle`](#from_pickle)\n    -   [`from_plist`](#from_plist)\n    -   [`from_query_string`](#from_query_string)\n    -   [`from_toml`](#from_toml)\n    -   [`from_xls`](#from_xls)\n    -   [`from_xml`](#from_xml)\n    -   [`from_yaml`](#from_yaml)\n    -   [`to_base64`](#to_base64)\n    -   [`to_csv`](#to_csv)\n    -   [`to_ini`](#to_ini)\n    -   [`to_json`](#to_json)\n    -   [`to_pickle`](#to_pickle)\n    -   [`to_plist`](#to_plist)\n    -   [`to_query_string`](#to_query_string)\n    -   [`to_toml`](#to_toml)\n    -   [`to_xml`](#to_xml)\n    -   [`to_yaml`](#to_yaml)\n\n-   **Parse methods**\n\n    -   [`get_bool`](#get_bool)\n    -   [`get_bool_list`](#get_bool_list)\n    -   [`get_date`](#get_date)\n    -   [`get_date_list`](#get_date_list)\n    -   [`get_datetime`](#get_datetime)\n    -   [`get_datetime_list`](#get_datetime_list)\n    -   [`get_decimal`](#get_decimal)\n    -   [`get_decimal_list`](#get_decimal_list)\n    -   [`get_dict`](#get_dict)\n    -   [`get_email`](#get_email)\n    -   [`get_float`](#get_float)\n    -   [`get_float_list`](#get_float_list)\n    -   [`get_int`](#get_int)\n    -   [`get_int_list`](#get_int_list)\n    -   [`get_list`](#get_list)\n    -   [`get_list_item`](#get_list_item)\n    -   [`get_phonenumber`](#get_phonenumber)\n    -   [`get_slug`](#get_slug)\n    -   [`get_slug_list`](#get_slug_list)\n    -   [`get_str`](#get_str)\n    -   [`get_str_list`](#get_str_list)\n    -   [`get_uuid`](#get_uuid)\n    -   [`get_uuid_list`](#get_uuid_list)\n\n### Utility methods\n\nThese methods are common utilities that will speed up your everyday work.\n\nUtilities that accept key argument(s) also support keypath(s).\n\nUtilities that return a dictionary always return a new `benedict` instance.\n\n#### `clean`\n\n```python\n# Clean the current dict instance removing all empty values: None, \"\", {}, [], ().\n# If strings or collections (dict, list, set, tuple) flags are False,\n# related empty values will not be deleted.\nd.clean(strings=True, collections=True)\n```\n\n#### `clone`\n\n```python\n# Return a clone (deepcopy) of the dict.\nc = d.clone()\n```\n\n#### `dump`\n\n```python\n# Return a readable representation of any dict/list.\n# This method can be used both as static method or instance method.\ns = benedict.dump(d.keypaths())\nprint(s)\n# or\nd = benedict()\nprint(d.dump())\n```\n\n#### `filter`\n\n```python\n# Return a filtered dict using the given predicate function.\n# Predicate function receives key, value arguments and should return a bool value.\npredicate = lambda k, v: v is not None\nf = d.filter(predicate)\n```\n\n#### `find`\n\n```python\n# Return the first match searching for the given keys/keypaths.\n# If no result found, default value is returned.\nkeys = [\"a.b.c\", \"m.n.o\", \"x.y.z\"]\nf = d.find(keys, default=0)\n```\n\n#### `flatten`\n\n```python\n# Return a new flattened dict using the given separator to join nested dict keys to flatten keypaths.\nf = d.flatten(separator=\"_\")\n```\n\n#### `groupby`\n\n```python\n# Group a list of dicts at key by the value of the given by_key and return a new dict.\ng = d.groupby(\"cities\", by_key=\"country_code\")\n```\n\n#### `invert`\n\n```python\n# Return an inverted dict where values become keys and keys become values.\n# Since multiple keys could have the same value, each value will be a list of keys.\n# If flat is True each value will be a single value (use this only if values are unique).\ni = d.invert(flat=False)\n```\n\n#### `items_sorted_by_keys`\n\n```python\n# Return items (key/value list) sorted by keys.\n# If reverse is True, the list will be reversed.\nitems = d.items_sorted_by_keys(reverse=False)\n```\n\n#### `items_sorted_by_values`\n\n```python\n# Return items (key/value list) sorted by values.\n# If reverse is True, the list will be reversed.\nitems = d.items_sorted_by_values(reverse=False)\n```\n\n#### `keypaths`\n\n```python\n# Return a list of all keypaths in the dict.\n# If indexes is True, the output will include list values indexes.\n# If sort is True, the resulting list will be sorted\nk = d.keypaths(indexes=False, sort=True)\n```\n\n#### `match`\n\n```python\n# Return a list of all values whose keypath matches the given pattern (a regex or string).\n# If pattern is string, wildcard can be used (eg. [*] can be used to match all list indexes).\n# If indexes is True, the pattern will be matched also against list values.\nm = d.match(pattern, indexes=True)\n```\n\n#### `merge`\n\n```python\n# Merge one or more dictionary objects into current instance (deepupdate).\n# Sub-dictionaries keys will be merged together.\n# If overwrite is False, existing values will not be overwritten.\n# If concat is True, list values will be concatenated together.\nd.merge(a, b, c, overwrite=True, concat=False)\n```\n\n#### `move`\n\n```python\n# Move an item from key_src to key_dst.\n# It can be used to rename a key.\n# If key_dst exists, its value will be overwritten.\nd.move(\"a\", \"b\", overwrite=True)\n```\n\n#### `nest`\n\n```python\n# Nest a list of dicts at the given key and return a new nested list\n# using the specified keys to establish the correct items hierarchy.\nd.nest(\"values\", id_key=\"id\", parent_id_key=\"parent_id\", children_key=\"children\")\n```\n\n#### `remove`\n\n```python\n# Remove multiple keys from the dict.\n# It is possible to pass a single key or more keys (as list or *args).\nd.remove([\"firstname\", \"lastname\", \"email\"])\n```\n\n#### `rename`\n\n```python\n# Rename a dict item key from \"key\" to \"key_new\".\n# If key_new exists, a KeyError will be raised.\nd.rename(\"first_name\", \"firstname\")\n```\n\n#### `search`\n\n```python\n# Search and return a list of items (dict, key, value, ) matching the given query.\nr = d.search(\"hello\", in_keys=True, in_values=True, exact=False, case_sensitive=False)\n```\n\n#### `standardize`\n\n```python\n# Standardize all dict keys, e.g. \"Location Latitude\" -\u003e \"location_latitude\".\nd.standardize()\n```\n\n#### `subset`\n\n```python\n# Return a dict subset for the given keys.\n# It is possible to pass a single key or more keys (as list or *args).\ns = d.subset([\"firstname\", \"lastname\", \"email\"])\n```\n\n#### `swap`\n\n```python\n# Swap items values at the given keys.\nd.swap(\"firstname\", \"lastname\")\n```\n\n#### `traverse`\n\n```python\n# Traverse a dict passing each item (dict, key, value) to the given callback function.\ndef f(d, key, value):\n    print(f\"dict: {d} - key: {key} - value: {value}\")\nd.traverse(f)\n```\n\n#### `unflatten`\n\n```python\n# Return a new unflattened dict using the given separator to split dict keys to nested keypaths.\nu = d.unflatten(separator=\"_\")\n```\n\n#### `unique`\n\n```python\n# Remove duplicated values from the dict.\nd.unique()\n```\n\n### I/O methods\n\nThese methods are available for input/output operations.\n\n#### `from_base64`\n\n```python\n# Try to load/decode a base64 encoded data and return it as benedict instance.\n# Accept as first argument: url, filepath or data-string.\n# It's possible to choose the subformat used under the hood:\n# ('csv', 'json', 'query-string', 'toml', 'xml', 'yaml'), default: 'json'.\n# It's possible to choose the encoding, default 'utf-8'.\n# A ValueError is raised in case of failure.\nd = benedict.from_base64(s, subformat=\"json\", encoding=\"utf-8\", **kwargs)\n```\n\n#### `from_cli`\n\n```python\n# Load and decode data from a string of CLI arguments.\n# ArgumentParser specific options can be passed using kwargs:\n# https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser\n# Return a new dict instance. A ValueError is raised in case of failure.\nd = benedict.from_cli(s, **kwargs)\n```\n\n#### `from_csv`\n\n```python\n# Try to load/decode a csv encoded data and return it as benedict instance.\n# Accept as first argument: url, filepath or data-string.\n# It's possible to specify the columns list, default: None (in this case the first row values will be used as keys).\n# It's possible to pass decoder specific options using kwargs:\n# https://docs.python.org/3/library/csv.html\n# A ValueError is raised in case of failure.\nd = benedict.from_csv(s, columns=None, columns_row=True, **kwargs)\n```\n\n#### `from_html`\n\n```python\n# Try to load/decode a html data and return it as benedict instance.\n# Accept as first argument: url, filepath or data-string.\n# It's possible to pass decoder specific options using kwargs:\n# https://beautiful-soup-4.readthedocs.io/\n# A ValueError is raised in case of failure.\nd = benedict.from_html(s, **kwargs)\n```\n\n#### `from_ini`\n\n```python\n# Try to load/decode a ini encoded data and return it as benedict instance.\n# Accept as first argument: url, filepath or data-string.\n# It's possible to pass decoder specific options using kwargs:\n# https://docs.python.org/3/library/configparser.html\n# A ValueError is raised in case of failure.\nd = benedict.from_ini(s, **kwargs)\n```\n\n#### `from_json`\n\n```python\n# Try to load/decode a json encoded data and return it as benedict instance.\n# Accept as first argument: url, filepath or data-string.\n# It's possible to pass decoder specific options using kwargs:\n# https://docs.python.org/3/library/json.html\n# A ValueError is raised in case of failure.\nd = benedict.from_json(s, **kwargs)\n```\n\n#### `from_pickle`\n\n```python\n# Try to load/decode a pickle encoded in Base64 format and return it as benedict instance.\n# Accept as first argument: url, filepath or data-string.\n# It's possible to pass decoder specific options using kwargs:\n# https://docs.python.org/3/library/pickle.html\n# A ValueError is raised in case of failure.\nd = benedict.from_pickle(s, **kwargs)\n```\n\n#### `from_plist`\n\n```python\n# Try to load/decode a p-list encoded data and return it as benedict instance.\n# Accept as first argument: url, filepath or data-string.\n# It's possible to pass decoder specific options using kwargs:\n# https://docs.python.org/3/library/plistlib.html\n# A ValueError is raised in case of failure.\nd = benedict.from_plist(s, **kwargs)\n```\n\n#### `from_query_string`\n\n```python\n# Try to load/decode a query-string and return it as benedict instance.\n# Accept as first argument: url, filepath or data-string.\n# A ValueError is raised in case of failure.\nd = benedict.from_query_string(s, **kwargs)\n```\n\n#### `from_toml`\n\n```python\n# Try to load/decode a toml encoded data and return it as benedict instance.\n# Accept as first argument: url, filepath or data-string.\n# It's possible to pass decoder specific options using kwargs:\n# https://pypi.org/project/toml/\n# A ValueError is raised in case of failure.\nd = benedict.from_toml(s, **kwargs)\n```\n\n#### `from_xls`\n\n```python\n# Try to load/decode a xls file (\".xls\", \".xlsx\", \".xlsm\") from url, filepath or data-string.\n# Accept as first argument: url, filepath or data-string.\n# It's possible to pass decoder specific options using kwargs:\n# - https://openpyxl.readthedocs.io/ (for .xlsx and .xlsm files)\n# - https://pypi.org/project/xlrd/ (for .xls files)\n# A ValueError is raised in case of failure.\nd = benedict.from_xls(s, sheet=0, columns=None, columns_row=True, **kwargs)\n```\n\n#### `from_xml`\n\n```python\n# Try to load/decode a xml encoded data and return it as benedict instance.\n# Accept as first argument: url, filepath or data-string.\n# It's possible to pass decoder specific options using kwargs:\n# https://github.com/martinblech/xmltodict\n# A ValueError is raised in case of failure.\nd = benedict.from_xml(s, **kwargs)\n```\n\n#### `from_yaml`\n\n```python\n# Try to load/decode a yaml encoded data and return it as benedict instance.\n# Accept as first argument: url, filepath or data-string.\n# It's possible to pass decoder specific options using kwargs:\n# https://pyyaml.org/wiki/PyYAMLDocumentation\n# A ValueError is raised in case of failure.\nd = benedict.from_yaml(s, **kwargs)\n```\n\n#### `to_base64`\n\n```python\n# Return the dict instance encoded in base64 format and optionally save it at the specified 'filepath'.\n# It's possible to choose the subformat used under the hood:\n# ('csv', json', 'query-string', 'toml', 'xml', 'yaml'), default: 'json'.\n# It's possible to choose the encoding, default 'utf-8'.\n# It's possible to pass decoder specific options using kwargs.\n# A ValueError is raised in case of failure.\ns = d.to_base64(subformat=\"json\", encoding=\"utf-8\", **kwargs)\n```\n\n#### `to_csv`\n\n```python\n# Return a list of dicts in the current dict encoded in csv format and optionally save it at the specified filepath.\n# It's possible to specify the key of the item (list of dicts) to encode, default: 'values'.\n# It's possible to specify the columns list, default: None (in this case the keys of the first item will be used).\n# A ValueError is raised in case of failure.\ns = d.to_csv(key=\"values\", columns=None, columns_row=True, **kwargs)\n```\n\n#### `to_ini`\n\n```python\n# Return the dict instance encoded in ini format and optionally save it at the specified filepath.\n# It's possible to pass encoder specific options using kwargs:\n# https://docs.python.org/3/library/configparser.html\n# A ValueError is raised in case of failure.\ns = d.to_ini(**kwargs)\n```\n\n#### `to_json`\n\n```python\n# Return the dict instance encoded in json format and optionally save it at the specified filepath.\n# It's possible to pass encoder specific options using kwargs:\n# https://docs.python.org/3/library/json.html\n# A ValueError is raised in case of failure.\ns = d.to_json(**kwargs)\n```\n\n#### `to_pickle`\n\n```python\n# Return the dict instance as pickle encoded in Base64 format and optionally save it at the specified filepath.\n# The pickle protocol used by default is 2.\n# It's possible to pass encoder specific options using kwargs:\n# https://docs.python.org/3/library/pickle.html\n# A ValueError is raised in case of failure.\ns = d.to_pickle(**kwargs)\n```\n\n#### `to_plist`\n\n```python\n# Return the dict instance encoded in p-list format and optionally save it at the specified filepath.\n# It's possible to pass encoder specific options using kwargs:\n# https://docs.python.org/3/library/plistlib.html\n# A ValueError is raised in case of failure.\ns = d.to_plist(**kwargs)\n```\n\n#### `to_query_string`\n\n```python\n# Return the dict instance as query-string and optionally save it at the specified filepath.\n# A ValueError is raised in case of failure.\ns = d.to_query_string(**kwargs)\n```\n\n#### `to_toml`\n\n```python\n# Return the dict instance encoded in toml format and optionally save it at the specified filepath.\n# It's possible to pass encoder specific options using kwargs:\n# https://pypi.org/project/toml/\n# A ValueError is raised in case of failure.\ns = d.to_toml(**kwargs)\n```\n\n#### `to_xml`\n\n```python\n# Return the dict instance encoded in xml format and optionally save it at the specified filepath.\n# It's possible to pass encoder specific options using kwargs:\n# https://github.com/martinblech/xmltodict\n# A ValueError is raised in case of failure.\ns = d.to_xml(**kwargs)\n```\n\n#### `to_yaml`\n\n```python\n# Return the dict instance encoded in yaml format.\n# If filepath option is passed the output will be saved ath\n# It's possible to pass encoder specific options using kwargs:\n# https://pyyaml.org/wiki/PyYAMLDocumentation\n# A ValueError is raised in case of failure.\ns = d.to_yaml(**kwargs)\n```\n\n### Parse methods\n\nThese methods are wrappers of the `get` method, they parse data trying to return it in the expected type.\n\n#### `get_bool`\n\n```python\n# Get value by key or keypath trying to return it as bool.\n# Values like `1`, `true`, `yes`, `on`, `ok` will be returned as `True`.\nd.get_bool(key, default=False)\n```\n\n#### `get_bool_list`\n\n```python\n# Get value by key or keypath trying to return it as list of bool values.\n# If separator is specified and value is a string it will be splitted.\nd.get_bool_list(key, default=[], separator=\",\")\n```\n\n#### `get_date`\n\n```python\n# Get value by key or keypath trying to return it as date.\n# If format is not specified it will be autodetected.\n# If choices and value is in choices return value otherwise default.\nd.get_date(key, default=None, format=None, choices=[])\n```\n\n#### `get_date_list`\n\n```python\n# Get value by key or keypath trying to return it as list of date values.\n# If separator is specified and value is a string it will be splitted.\nd.get_date_list(key, default=[], format=None, separator=\",\")\n```\n\n#### `get_datetime`\n\n```python\n# Get value by key or keypath trying to return it as datetime.\n# If format is not specified it will be autodetected.\n# If choices and value is in choices return value otherwise default.\nd.get_datetime(key, default=None, format=None, choices=[])\n```\n\n#### `get_datetime_list`\n\n```python\n# Get value by key or keypath trying to return it as list of datetime values.\n# If separator is specified and value is a string it will be splitted.\nd.get_datetime_list(key, default=[], format=None, separator=\",\")\n```\n\n#### `get_decimal`\n\n```python\n# Get value by key or keypath trying to return it as Decimal.\n# If choices and value is in choices return value otherwise default.\nd.get_decimal(key, default=Decimal(\"0.0\"), choices=[])\n```\n\n#### `get_decimal_list`\n\n```python\n# Get value by key or keypath trying to return it as list of Decimal values.\n# If separator is specified and value is a string it will be splitted.\nd.get_decimal_list(key, default=[], separator=\",\")\n```\n\n#### `get_dict`\n\n```python\n# Get value by key or keypath trying to return it as dict.\n# If value is a json string it will be automatically decoded.\nd.get_dict(key, default={})\n```\n\n#### `get_email`\n\n```python\n# Get email by key or keypath and return it.\n# If value is blacklisted it will be automatically ignored.\n# If check_blacklist is False, it will be not ignored even if blacklisted.\nd.get_email(key, default=\"\", choices=None, check_blacklist=True)\n```\n\n#### `get_float`\n\n```python\n# Get value by key or keypath trying to return it as float.\n# If choices and value is in choices return value otherwise default.\nd.get_float(key, default=0.0, choices=[])\n```\n\n#### `get_float_list`\n\n```python\n# Get value by key or keypath trying to return it as list of float values.\n# If separator is specified and value is a string it will be splitted.\nd.get_float_list(key, default=[], separator=\",\")\n```\n\n#### `get_int`\n\n```python\n# Get value by key or keypath trying to return it as int.\n# If choices and value is in choices return value otherwise default.\nd.get_int(key, default=0, choices=[])\n```\n\n#### `get_int_list`\n\n```python\n# Get value by key or keypath trying to return it as list of int values.\n# If separator is specified and value is a string it will be splitted.\nd.get_int_list(key, default=[], separator=\",\")\n```\n\n#### `get_list`\n\n```python\n# Get value by key or keypath trying to return it as list.\n# If separator is specified and value is a string it will be splitted.\nd.get_list(key, default=[], separator=\",\")\n```\n\n#### `get_list_item`\n\n```python\n# Get list by key or keypath and return value at the specified index.\n# If separator is specified and list value is a string it will be splitted.\nd.get_list_item(key, index=0, default=None, separator=\",\")\n```\n\n#### `get_phonenumber`\n\n```python\n# Get phone number by key or keypath and return a dict with different formats (e164, international, national).\n# If country code is specified (alpha 2 code), it will be used to parse phone number correctly.\nd.get_phonenumber(key, country_code=None, default=None)\n```\n\n#### `get_slug`\n\n```python\n# Get value by key or keypath trying to return it as slug.\n# If choices and value is in choices return value otherwise default.\nd.get_slug(key, default=\"\", choices=[])\n```\n\n#### `get_slug_list`\n\n```python\n# Get value by key or keypath trying to return it as list of slug values.\n# If separator is specified and value is a string it will be splitted.\nd.get_slug_list(key, default=[], separator=\",\")\n```\n\n#### `get_str`\n\n```python\n# Get value by key or keypath trying to return it as string.\n# Encoding issues will be automatically fixed.\n# If choices and value is in choices return value otherwise default.\nd.get_str(key, default=\"\", choices=[])\n```\n\n#### `get_str_list`\n\n```python\n# Get value by key or keypath trying to return it as list of str values.\n# If separator is specified and value is a string it will be splitted.\nd.get_str_list(key, default=[], separator=\",\")\n```\n\n#### `get_uuid`\n\n```python\n# Get value by key or keypath trying to return it as valid uuid.\n# If choices and value is in choices return value otherwise default.\nd.get_uuid(key, default=\"\", choices=[])\n```\n\n#### `get_uuid_list`\n\n```python\n# Get value by key or keypath trying to return it as list of valid uuid values.\n# If separator is specified and value is a string it will be splitted.\nd.get_uuid_list(key, default=[], separator=\",\")\n```\n\n## Testing\n```bash\n# clone repository\ngit clone https://github.com/fabiocaccamo/python-benedict.git \u0026\u0026 cd python-benedict\n\n# create virtualenv and activate it\npython -m venv venv \u0026\u0026 . venv/bin/activate\n\n# upgrade pip\npython -m pip install --upgrade pip\n\n# install requirements\npip install -r requirements.txt -r requirements-test.txt\n\n# install pre-commit to run formatters and linters\npre-commit install --install-hooks\n\n# run tests using tox\ntox\n\n# or run tests using unittest\npython -m unittest\n```\n\n## License\nReleased under [MIT License](LICENSE.txt).\n\n---\n\n## Supporting\n\n- :star: Star this project on [GitHub](https://github.com/fabiocaccamo/python-benedict)\n- :octocat: Follow me on [GitHub](https://github.com/fabiocaccamo)\n- :blue_heart: Follow me on [Twitter](https://twitter.com/fabiocaccamo)\n- :moneybag: Sponsor me on [Github](https://github.com/sponsors/fabiocaccamo)\n\n## See also\n\n- [`python-fontbro`](https://github.com/fabiocaccamo/python-fontbro) - 🧢 friendly font operations on top of `fontTools`.\n\n- [`python-fsutil`](https://github.com/fabiocaccamo/python-fsutil) - 🧟‍♂️ high-level file-system operations for lazy devs.\n","funding_links":["https://github.com/sponsors/fabiocaccamo","https://polar.sh/fabiocaccamo","https://ko-fi.com/fabiocaccamo","https://liberapay.com/fabiocaccamo","https://tidelift.com/funding/github/pypi/python-benedict","https://www.buymeacoffee.com/fabiocaccamo","https://www.paypal.me/fabiocaccamo"],"categories":["Python","Data Structures"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffabiocaccamo%2Fpython-benedict","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffabiocaccamo%2Fpython-benedict","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffabiocaccamo%2Fpython-benedict/lists"}