jsonobject
jsonobject is a Python library for handling deeply nested JSON objects as well-schema'd Python objects. It provides a declarative way to define data models for JSON structures, facilitating easy serialization and deserialization between Python objects and JSON. Maintained by Dimagi, it is currently at version 2.3.1 and typically follows an active release cadence.
Common errors
-
AttributeError: 'dict' object has no attribute 'some_property'
cause Attempting to access a property on a standard Python dictionary (`dict`) as if it were a `jsonobject.JsonObject` instance. This occurs when JSON data has been loaded using `json.loads()` or similar, but not wrapped/instantiated as a `JsonObject`.fixEnsure that your dictionary is correctly passed to the `JsonObject` constructor: `my_object = MyJsonObject(my_dict_data)`. -
jsonobject.exceptions.BadValueError: Expected type <ExpectedType>, got <ActualType>
cause A value assigned to a `Property` or provided during `JsonObject` instantiation does not match the expected type defined in the schema (e.g., providing a string to an `IntegerProperty`).fixCheck the schema definition for the property (`e.g., IntegerProperty()`) and ensure the data being assigned or provided conforms to that type. Explicitly convert data types if necessary before assignment. -
json.decoder.JSONDecodeError: Expecting value: line X column Y (char Z)
cause The input string provided to `JsonObject` constructor (or `json.loads` if you're manually parsing) is not valid JSON. This can be due to missing quotes, unescaped characters, trailing commas, or incorrect bracket/brace balancing.fixValidate your JSON string using a linter or online tool before passing it to `jsonobject`. Common fixes include ensuring all keys and string values use double quotes, no trailing commas, and balanced brackets/braces. -
TypeError: 'PropertyName' object is not subscriptable
cause Attempting to access an attribute of a `JsonObject` (which is a `Property` object) using square brackets (`[]`) as if it were a dictionary or list, when it is not. For example, trying `user.username[0]` for a `StringProperty`.fixAccess `Property` values directly as attributes (e.g., `user.username`). If the property is indeed a list or dict (`ListProperty`, `DictProperty`), then subscripting is valid for its *value*, but not the `Property` object itself.
Warnings
- breaking Version 2.0.0 changed the behavior of `ListProperty` when an iterable is passed as its value type. Previously, it might have raised `BadValueError`; now, it returns a plain Python list. This was considered a fix for unintuitive behavior but could be breaking if previous error handling was relied upon.
- breaking Version 1.0.0 officially dropped support for Python 2.7, 3.5, and 3.6. Using `jsonobject` 1.0.0 or higher with these Python versions will result in compatibility errors.
- gotcha When defining `Property` types, be cautious with mutable default values (e.g., `ListProperty(default=[])` or `DictProperty(default={})`). If a mutable object is used as a default, all instances of the `JsonObject` class will share the *same* mutable object, leading to unexpected side effects when one instance modifies it.
- gotcha The `jsonobject` library provides schema-driven object mapping for JSON. It is distinct from Python's built-in `json` module, which offers basic JSON encoding/decoding, and also distinct from Java libraries often named `JSONObject`. Avoid confusing their APIs or expecting direct interoperability without explicit conversion.
Install
-
pip install jsonobject
Imports
- JsonObject
from jsonobject import JsonObject
- StringProperty
from jsonobject import StringProperty
- IntegerProperty
from jsonobject import IntegerProperty
- BooleanProperty
from jsonobject import BooleanProperty
- DateTimeProperty
from jsonobject import DateTimeProperty
- ListProperty
from jsonobject import ListProperty
- DictProperty
from jsonobject import DictProperty
Quickstart
import datetime
from jsonobject import JsonObject, StringProperty, BooleanProperty, DateTimeProperty, ListProperty
class User(JsonObject):
username = StringProperty(required=True)
name = StringProperty()
active = BooleanProperty(default=False)
date_joined = DateTimeProperty()
tags = ListProperty(str)
# Create an object
user1 = User(
name='Jane Doe',
username='janedoe',
date_joined=datetime.datetime.utcnow(),
tags=['developer', 'python']
)
print(f"User object: {user1}")
print(f"User to JSON: {user1.to_json()}")
# Create from existing JSON
json_data = {
'username': 'alice',
'name': 'Alice Smith',
'active': True,
'date_joined': '2023-01-15T10:30:00Z',
'tags': ['tester']
}
user2 = User(json_data)
print(f"User from JSON: {user2}")
print(f"Is user2 active? {user2.active}")