{"id":648,"library":"jsonref","title":"jsonref: JSON Reference Dereferencing","description":"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.","status":"active","version":"1.1.0","language":"python","source_language":"en","source_url":"https://github.com/gazpachoking/jsonref","tags":["JSON","reference","dereferencing","schema","lazy loading"],"install":[{"cmd":"pip install jsonref","lang":"bash","label":"Install with pip"}],"dependencies":[{"reason":"Used for fetching HTTP/HTTPS URIs if available; falls back to urllib otherwise.","package":"requests","optional":true}],"imports":[{"note":"Used for parsing JSON strings with references directly.","symbol":"loads","correct":"import jsonref\ndata = jsonref.loads(json_string)"},{"note":"The class method `JsonRef.replace_refs` is deprecated since version 0.4; use the top-level function `jsonref.replace_refs` instead.","wrong":"from jsonref import JsonRef\ndereferenced_obj = JsonRef.replace_refs(python_object)","symbol":"replace_refs","correct":"from jsonref import replace_refs\ndereferenced_obj = replace_refs(python_object)"},{"note":"Represents a lazy-loading proxy to dereferenced data. Instances proxy almost all operators and attributes to the referent data.","symbol":"JsonRef","correct":"from jsonref import JsonRef"},{"note":"Exception raised when a JSON reference resolution fails.","symbol":"JsonRefError","correct":"from jsonref import JsonRefError"}],"quickstart":{"code":"import jsonref\nimport json\n\n# Example 1: Loading from a JSON string with internal references\njson_str = '''\n{\n    \"data\": [1, 2, 3, 4],\n    \"ref_to_data\": {\"$ref\": \"#/data\"},\n    \"ref_to_item\": {\"$ref\": \"#/data/1\"}\n}\n'''\ndata_from_str = jsonref.loads(json_str)\n\nprint(\"--- From jsonref.loads ---\")\nprint(f\"Original data: {data_from_str['data']}\")\nprint(f\"Reference to data: {data_from_str['ref_to_data']}\") # Lazy loaded when accessed\nprint(f\"Reference to item: {data_from_str['ref_to_item']}\") # Lazy loaded when accessed\nprint(f\"Is ref_to_data a JsonRef instance? {isinstance(data_from_str['ref_to_data'], jsonref.JsonRef)}\")\nprint(f\"Direct access to referent: {data_from_str['ref_to_data'].__subject__}\")\nprint(f\"Original reference object: {data_from_str['ref_to_data'].__reference__}\")\n\n# Example 2: Replacing references in an existing Python object\nfrom jsonref import replace_refs\n\npython_obj = {\n    \"items\": [\"apple\", \"banana\", \"cherry\"],\n    \"first_item_ref\": {\"$ref\": \"#/items/0\"}\n}\n\ndereferenced_obj = replace_refs(python_obj)\n\nprint(\"\\n--- From jsonref.replace_refs ---\")\nprint(f\"Original Python object: {json.dumps(python_obj)}\")\nprint(f\"Dereferenced object: {json.dumps(dereferenced_obj)}\")\nprint(f\"Accessing dereferenced value: {dereferenced_obj['first_item_ref']}\")\n\n# Example 3: Handling external references (requires 'requests' or will use urllib)\n# For external references, a loader can be specified. jsonloader is the default.\n# This example is conceptual as 'example.com/schema.json' is not guaranteed to exist.\n# If you have a local 'schema.json' with {\"version\": \"1.0\"}, use 'file:///path/to/schema.json'\nexternal_ref_schema = {\n    \"my_schema\": {\"$ref\": \"http://example.com/schema.json#/version\"}\n}\n# Assuming http://example.com/schema.json contains {\"version\": \"1.0\"}\n# This would attempt to fetch the external URI:\ntry:\n    # Use a mock loader for demonstration, as live external URIs might be flaky\n    def mock_loader(uri):\n        if uri == \"http://example.com/schema.json\":\n            return {\"version\": \"1.0\", \"description\": \"A simple schema\"}\n        raise JsonRefError(f\"Unknown URI: {uri}\", reference={'$ref': uri})\n\n    external_data = replace_refs(external_ref_schema, loader=mock_loader)\n    print(\"\\n--- External Reference Example (Conceptual) ---\")\n    print(f\"External data reference: {external_data['my_schema']}\")\nexcept JsonRefError as e:\n    print(f\"\\nCould not resolve external reference (expected if example.com is not valid): {e.message}\")","lang":"python","description":"Demonstrates loading JSON with references using `jsonref.loads`, dereferencing an existing Python object with `jsonref.replace_refs`, and a conceptual example of handling external references using a custom loader. It highlights how `JsonRef` objects act as lazy proxies to the underlying data."},"warnings":[{"fix":"Rewrite code that subclassed `JsonLoader` to adapt to `jsonloader` being a standalone function. Review the `loader` parameter in `replace_refs` and `loads`.","message":"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.","severity":"breaking","affected_versions":">=0.4"},{"fix":"Change calls from `JsonRef.replace_refs(obj)` to `jsonref.replace_refs(obj)`.","message":"The class method `JsonRef.replace_refs()` is deprecated. You should use the top-level function `jsonref.replace_refs()` instead.","severity":"deprecated","affected_versions":">=0.4"},{"fix":"Be aware that simply accessing a `JsonRef` instance will trigger lazy loading. If you need the raw reference or the underlying data without proxy behavior, use `.__reference__` or `.__subject__` respectively.","message":"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__`.","severity":"gotcha","affected_versions":"All versions"},{"fix":"If working with JSON Schema, set `jsonschema=True`. Be mindful that base URIs must be provided explicitly or derived from the resource's load location, as `$id` will not automatically change it within `jsonref`.","message":"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.","severity":"gotcha","affected_versions":"All versions"},{"fix":"If you need to serialize the fully dereferenced content, ensure all `JsonRef` objects have been accessed (thus loaded) and then use standard `json.dumps()` on the resulting Python object. Alternatively, convert `JsonRef` objects to their `__subject__` if necessary before dumping.","message":"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.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-05-12T17:14:12.555Z","next_check":"2026-09-28T00:00:00.000Z","problems":[{"fix":"Upgrade `jsonref` to the latest version using `pip install --upgrade jsonref` to ensure compatibility with recent API changes. If using a dependency manager like `pipenv` or `conda`, ensure `jsonref` is updated to a compatible version.","cause":"This error often occurs when an older version of `jsonref` is installed, or when a dependent library expects a newer API that includes `URIDict`, which was removed or refactored in `jsonref` versions 1.0.0 and above.","error":"ImportError: cannot import name 'URIDict' from 'jsonref'"},{"fix":"Inspect your JSON schema for circular references or excessively deep nesting. If the recursion is legitimate, you can temporarily increase Python's recursion limit for complex documents using `import sys; sys.setrecursionlimit(YOUR_NEW_LIMIT)`. However, it's often better to resolve circular dependencies in the schema itself if possible.","cause":"This error typically arises when processing JSON documents with deeply nested or circular `$ref` references, causing `jsonref`'s dereferencing logic to enter an infinite loop or exceed Python's default recursion limit.","error":"RecursionError: maximum recursion depth exceeded"},{"fix":"Validate your JSON input using a JSON linter or validator. Common issues include missing commas, unquoted keys or string values, incorrect use of single vs. double quotes, or unclosed brackets. Ensure the input is valid JSON before passing it to `jsonref`.","cause":"This error indicates that the input JSON document provided to `jsonref.loads()` or `jsonref.load()` is syntactically incorrect, preventing the underlying `json` module from parsing it before `jsonref` can process references.","error":"json.decoder.JSONDecodeError: Expecting value: line X column Y (char Z)"},{"fix":"Verify that the URI in your `$ref` points to a valid location, both for internal document references (JSON Pointers) and external URIs. Ensure that any external files are accessible and contain valid JSON. Check for typos in the reference path or filename.","cause":"This is a general error raised by `jsonref` when it encounters a JSON Reference (`$ref`) that it cannot successfully resolve, often due to a malformed URI, a non-existent path within the document, or an inaccessible external file.","error":"JsonRefError: Unable to resolve reference: '#/some/path'"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":0,"quickstart_tag":"stale","pypi_latest":"1.1.0","install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.08,"mem_mb":3.6,"disk_size":"17.8M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.08,"mem_mb":3.6,"disk_size":"17.8M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.5,"import_time_s":0.06,"mem_mb":3.6,"disk_size":"18M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.06,"mem_mb":3.6,"disk_size":"18M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.13,"mem_mb":4,"disk_size":"19.7M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.13,"mem_mb":4,"disk_size":"19.7M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.8,"import_time_s":0.12,"mem_mb":4,"disk_size":"20M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.11,"mem_mb":4,"disk_size":"20M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.1,"mem_mb":3.8,"disk_size":"11.6M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.1,"mem_mb":3.8,"disk_size":"11.6M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.5,"import_time_s":0.12,"mem_mb":3.8,"disk_size":"12M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.1,"mem_mb":3.8,"disk_size":"12M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.08,"mem_mb":3.6,"disk_size":"11.3M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.09,"mem_mb":3.6,"disk_size":"11.2M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.4,"import_time_s":0.08,"mem_mb":3.4,"disk_size":"12M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.08,"mem_mb":3.4,"disk_size":"12M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.08,"mem_mb":3.8,"disk_size":"17.3M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.11,"mem_mb":3.8,"disk_size":"17.3M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.7,"import_time_s":0.07,"mem_mb":3.8,"disk_size":"18M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.07,"mem_mb":3.8,"disk_size":"18M"}]},"quickstart_checks":{"last_tested":"2026-04-24","tag":"stale","tag_description":"widespread failures or data too old to trust","results":[{"runtime":"python:3.10-alpine","exit_code":1},{"runtime":"python:3.10-slim","exit_code":1},{"runtime":"python:3.11-alpine","exit_code":1},{"runtime":"python:3.11-slim","exit_code":1},{"runtime":"python:3.12-alpine","exit_code":1},{"runtime":"python:3.12-slim","exit_code":1},{"runtime":"python:3.13-alpine","exit_code":1},{"runtime":"python:3.13-slim","exit_code":1},{"runtime":"python:3.9-alpine","exit_code":1},{"runtime":"python:3.9-slim","exit_code":1}]}}