jsonref: JSON Reference Dereferencing
jsonref is a Python library (supporting Python 3.7+) for automatic dereferencing of JSON Reference objects within JSON documents. It allows you to work with data structures containing JSON references as if they were already replaced with their referent data, supporting lazy and recursive dereferencing. The current version is 1.1.0, with its last release in January 2023, indicating active maintenance.
Warnings
- breaking The `jsonloader` utility (for loading URIs) changed from being an instance of a class to a plain function. If you were subclassing `JsonLoader` prior to version 0.4, your code will break.
- deprecated The class method `JsonRef.replace_refs()` is deprecated. You should use the top-level function `jsonref.replace_refs()` instead.
- gotcha When working with `JsonRef` proxy objects, direct access to the dereferenced subject is via the `__subject__` attribute (which forces loading if lazy). The original reference object can be accessed via `__reference__`.
- gotcha The `jsonschema=True` parameter in `loads` and `replace_refs` changes how object identifiers are handled, defaulting to `$id` instead of `id` (like JSON Schema draft v06+). This also means `$id` does *not* establish the base URI for references within the document, differing from canonical JSON Schema.
- gotcha Unlike the standard `json.dumps()` or `json.dump()`, `jsonref.dumps()` and `jsonref.dump()` will serialize `JsonRef` instances back into their *original JSON Reference objects*, not their dereferenced values. This is by design to preserve the reference structure.
Install
-
pip install jsonref
Imports
- loads
import jsonref data = jsonref.loads(json_string)
- replace_refs
from jsonref import replace_refs dereferenced_obj = replace_refs(python_object)
- JsonRef
from jsonref import JsonRef
- JsonRefError
from jsonref import JsonRefError
Quickstart
import jsonref
import json
# Example 1: Loading from a JSON string with internal references
json_str = '''
{
"data": [1, 2, 3, 4],
"ref_to_data": {"$ref": "#/data"},
"ref_to_item": {"$ref": "#/data/1"}
}
'''
data_from_str = jsonref.loads(json_str)
print("--- From jsonref.loads ---")
print(f"Original data: {data_from_str['data']}")
print(f"Reference to data: {data_from_str['ref_to_data']}") # Lazy loaded when accessed
print(f"Reference to item: {data_from_str['ref_to_item']}") # Lazy loaded when accessed
print(f"Is ref_to_data a JsonRef instance? {isinstance(data_from_str['ref_to_data'], jsonref.JsonRef)}")
print(f"Direct access to referent: {data_from_str['ref_to_data'].__subject__}")
print(f"Original reference object: {data_from_str['ref_to_data'].__reference__}")
# Example 2: Replacing references in an existing Python object
from jsonref import replace_refs
python_obj = {
"items": ["apple", "banana", "cherry"],
"first_item_ref": {"$ref": "#/items/0"}
}
dereferenced_obj = replace_refs(python_obj)
print("\n--- From jsonref.replace_refs ---")
print(f"Original Python object: {json.dumps(python_obj)}")
print(f"Dereferenced object: {json.dumps(dereferenced_obj)}")
print(f"Accessing dereferenced value: {dereferenced_obj['first_item_ref']}")
# Example 3: Handling external references (requires 'requests' or will use urllib)
# For external references, a loader can be specified. jsonloader is the default.
# This example is conceptual as 'example.com/schema.json' is not guaranteed to exist.
# If you have a local 'schema.json' with {"version": "1.0"}, use 'file:///path/to/schema.json'
external_ref_schema = {
"my_schema": {"$ref": "http://example.com/schema.json#/version"}
}
# Assuming http://example.com/schema.json contains {"version": "1.0"}
# This would attempt to fetch the external URI:
try:
# Use a mock loader for demonstration, as live external URIs might be flaky
def mock_loader(uri):
if uri == "http://example.com/schema.json":
return {"version": "1.0", "description": "A simple schema"}
raise JsonRefError(f"Unknown URI: {uri}", reference={'$ref': uri})
external_data = replace_refs(external_ref_schema, loader=mock_loader)
print("\n--- External Reference Example (Conceptual) ---")
print(f"External data reference: {external_data['my_schema']}")
except JsonRefError as e:
print(f"\nCould not resolve external reference (expected if example.com is not valid): {e.message}")