{"id":7421,"library":"mo-dots","title":"mo-dots: Dot-Access to Python Dictionaries","description":"mo-dots is a Python library that provides 'dot-access' functionality to dictionary-like data structures, similar to JavaScript objects. It boxes JSON-like data into a `Data` object, offering null-safe attribute access and a consistent interface. The library aims to be a more consistent and easier-to-use replacement for standard Python dictionaries, facilitating data transformation tasks. It is actively maintained, with the current version being 10.685.25166.","status":"active","version":"10.685.25166","language":"en","source_language":"en","source_url":"https://github.com/klahnakoski/mo-dots","tags":["dictionary","dot-access","data-structures","json","null-safe","dict-replacement"],"install":[{"cmd":"pip install mo-dots","lang":"bash","label":"Install latest version"}],"dependencies":[],"imports":[{"note":"The primary class for dot-accessible data is 'Data' and it's intended for direct import.","wrong":"import mo_dots.Data","symbol":"Data","correct":"from mo_dots import Data"},{"note":"Used to convert existing dicts to Data objects.","symbol":"to_data","correct":"from mo_dots import to_data"},{"note":"Essential for serializing Data objects to standard JSON.","symbol":"from_data","correct":"from mo_dots import from_data"}],"quickstart":{"code":"import json\nfrom mo_dots import Data, to_data, from_data\n\n# Create a Data object directly\nd = Data(a=1, b={'c': 2, 'd': [3, 4]})\nprint(f\"Initial Data object: {d}\")\n\n# Access with dot notation (null-safe)\nprint(f\"d.a: {d.a}\")\nprint(f\"d.b.c: {d.b.c}\")\nprint(f\"d.b.e: {d.b.e} (returns Null, not KeyError)\")\n\n# Path assignment\nd['x.y.z'] = 99\nprint(f\"After path assignment: {d}\")\n\n# Path accumulation with +=\nd.stats.count += 1 # Initializes to 0 then adds 1\nd.stats.items += ['apple'] # Initializes to [] then appends\nd.stats.items += ['banana']\nprint(f\"After path accumulation: {d}\")\n\n# Convert an existing dictionary\nmy_dict = {'user': {'name': 'Alice', 'id': 123}}\ndata_from_dict = to_data(my_dict)\nprint(f\"Data from dict: {data_from_dict.user.name}\")\n\n# Serialize to JSON (requires from_data)\ntry:\n    json.dumps(d) # This will raise TypeError without default=from_data\nexcept TypeError as e:\n    print(f\"Caught expected TypeError during direct JSON serialization: {e}\")\n\njson_output = json.dumps(d, default=from_data)\nprint(f\"JSON output: {json_output}\")\nassert json.loads(json_output) == {'a': 1, 'b': {'c': 2, 'd': [3, 4]}, 'x': {'y': {'z': 99}}, 'stats': {'count': 1, 'items': ['apple', 'banana']}}","lang":"python","description":"This quickstart demonstrates how to create `Data` objects, access nested properties using dot notation and path strings, perform path assignments, and handle the specialized path accumulation with `+=`. It also highlights the crucial step for JSON serialization using `from_data`."},"warnings":[{"fix":"When serializing `Data` objects to JSON, use `json.dumps(data_object, default=from_data)` to convert `Data` structures into Python primitives.","message":"The standard Python `json` library does not natively recognize `mo_dots.Data` objects for serialization, leading to `TypeError`.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Always check for `Null` when accessing potentially non-existent paths, or use `data.get('path', default_value)` for explicit default handling if `Null` is not desired. Be aware that subsequent operations on a `Null` value will raise `AttributeError`.","message":"Accessing a non-existent key or attribute on a `Data` object using dot notation (`data.non_existent`) or bracket notation (`data['non.existent']`) will return `Null` instead of raising a `KeyError` or `AttributeError`.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Understand this automatic initialization. If you require different default behavior for new paths or explicit control over type initialization, initialize the path yourself (e.g., `data.new_path = 0` or `data.new_path = []`) before using `+=`.","message":"The `+=` operator on a non-existent path (`data.new_path += value`) has special behavior: for numerical types, `new_path` is initialized to `0` before adding `value`; for list types, `new_path` is initialized to `[]` before appending `value`.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Import `from_data` and pass it to the `default` argument of `json.dumps()`: `json.dumps(my_data, default=from_data)`.","cause":"`json.dumps()` was called directly on a `mo_dots.Data` object without a custom default serializer.","error":"TypeError: Object of type Data is not JSON serializable"},{"fix":"For `Data` objects, non-existent keys accessed via dot notation (e.g., `data.some_missing_key`) or path strings (e.g., `data['a.b.c']`) will return `Null`. If you are explicitly trying to catch `KeyError`, ensure you are using standard dicts or adapt to `mo-dots`'s null-safe behavior. If you are getting this with `data[key]`, check if `key` actually exists or use `data.get(key)`.","cause":"Attempting to access a non-existent key on a `mo_dots.Data` object using standard dictionary bracket notation, but `mo-dots` usually returns `Null` for missing keys accessed via dot notation or path strings, and handles some bracket accesses differently.","error":"KeyError: 'some_missing_key'"},{"fix":"Always check if a path exists or returns `Null` before performing further operations on it. For example, `if data.path and data.path.attribute: ...` or `value = data.get('path.attribute', None); if value is not None: ...`","cause":"A chained dot access or an operation was attempted on a `Null` value, which was returned by `mo-dots` for a non-existent path.","error":"AttributeError: 'Null' object has no attribute 'some_method'"}]}