### Install ijson using pip Source: https://github.com/icrar/ijson/blob/master/README.rst Install the ijson library using pip. Binary wheels are provided for major platforms and Python versions. ```bash pip install ijson ``` -------------------------------- ### Install ijson with cffi Source: https://github.com/icrar/ijson/blob/master/_autodocs/06-backends.md Install ijson, which automatically integrates with cffi for YAJL 2.x bindings. Alternatively, install cffi separately before installing ijson. ```bash pip install ijson ``` ```bash pip install cffi pip install ijson ``` -------------------------------- ### Install ijson with YAJL 2.x C Extension Source: https://github.com/icrar/ijson/blob/master/_autodocs/06-backends.md Install the ijson package, which typically includes the fast C extension for YAJL 2.x. If compilation is needed, ensure YAJL development files are installed. ```bash pip install ijson ``` ```bash pip install --no-binary=ijson ijson ``` -------------------------------- ### Usage Patterns Source: https://github.com/icrar/ijson/blob/master/_autodocs/README.md Examples and techniques for using ijson, including stream processing, async/await, and advanced patterns like validation and database streaming. ```APIDOC ## Pull Interfaces (File-based) **Description**: Examples of using ijson with file-based input. ## Stream Processing ### HTTP with requests, httpx **Description**: Demonstrates processing JSON streams from HTTP requests using libraries like `requests` and `httpx`. ## Async/await Patterns **Description**: Usage examples employing asynchronous programming with `async`/`await`. ## Push Interfaces (Coroutines) **Description**: Examples of using ijson with coroutine-based push interfaces. ## Event Filtering and Transformation **Description**: Techniques for filtering and transforming the event stream. ## Advanced Patterns ### Validation, Batching, Database Streaming **Description**: Examples of advanced use cases such as data validation, batch processing, and streaming data to databases. ## Performance Optimization Techniques **Description**: Strategies for optimizing ijson's performance in various scenarios. ``` -------------------------------- ### Importing a Specific ijson Backend Source: https://github.com/icrar/ijson/blob/master/README.rst This example shows how to import and use a specific ijson backend, in this case 'yajl2_cffi'. This allows for potentially faster parsing if the backend is available. The rest of the ijson API remains the same. ```python import ijson.backends.yajl2_cffi as ijson for item in ijson.items(...): # ... ``` -------------------------------- ### Force Use of Python Backend Source: https://github.com/icrar/ijson/blob/master/_autodocs/02-main-api.md Dynamically import and use the 'python' backend for parsing JSON. This example demonstrates how to explicitly select a backend module and use its `items` function. ```python import ijson # Force use of Python backend backend = ijson.get_backend('python') for item in backend.items(json_source, 'data.item'): print(item) ``` -------------------------------- ### Force YAJL 2.x C Extension Backend Source: https://github.com/icrar/ijson/blob/master/_autodocs/00-TABLE-OF-CONTENTS.md Explicitly selects the yajl2_c backend, which is a C extension providing high performance. Ensure the extension is installed. ```python backend = ijson.get_backend('yajl2_c') ``` -------------------------------- ### Error Reference Source: https://github.com/icrar/ijson/blob/master/_autodocs/README.md Comprehensive guide to ijson's exception classes, error handling patterns, and debugging techniques. ```APIDOC ## Exception Classes ### `JSONError` **Description**: Raised for JSON syntax errors during parsing. ### `IncompleteJSONError` **Description**: Raised when the input JSON is truncated. ### `ValueError` **Description**: Raised for invalid configuration settings. ## Backend-Specific Exceptions **Description**: Lists exceptions that may be raised by specific backends. ## Error Handling Patterns **Description**: Recommended patterns for handling errors gracefully. ## Debugging Techniques **Description**: Strategies for debugging parsing issues and errors. ## Common Issues and Solutions **Description**: A collection of frequently encountered problems and their resolutions. ``` -------------------------------- ### Catching YAJLImportError for Missing YAJL Library Source: https://github.com/icrar/ijson/blob/master/_autodocs/05-errors.md Use this example to catch `YAJLImportError` when the YAJL library is not available. It demonstrates a common fallback strategy to use the pure Python backend instead. ```python import ijson try: backend = ijson.get_backend('yajl2_c') except ijson.backends.YAJLImportError as e: print(f"YAJL not available: {e}") # Fall back to Python backend backend = ijson.get_backend('python') ``` -------------------------------- ### Python Coroutine Implementation Example Source: https://github.com/icrar/ijson/blob/master/notes/design_notes.rst Illustrates how 'pre-chained' coroutines are implemented by chaining base coroutines. Use this pattern for simplified iterator construction. ```python def parse_coro(target, ...): return basic_parse_basecoro(parse_basecoro(target), ...) ``` -------------------------------- ### ijson Prefix Format Examples Source: https://github.com/icrar/ijson/blob/master/_autodocs/04-types.md Shows the string format used for prefixes, representing the path to an event within the JSON structure. Prefixes are constructed by appending object keys or array indices, separated by dots. ```text # Format examples: "" # Root level "key" # Object member "key" "key.subkey" # Nested object member "array.item" # Array element "array.item.key" # Object within array "data.items.item.meta" # Deeply nested ``` -------------------------------- ### Parsing JSON object start and end Source: https://github.com/icrar/ijson/blob/master/_autodocs/07-events.md Illustrates capturing ('start_map', None) and ('end_map', None) events for JSON object delimiters. ```python depth = 0 for event_type, value in ijson.basic_parse(b'{"nested":{"key":"value"}}'): if event_type == 'start_map': print(f"Object start (depth={depth})") depth += 1 elif event_type == 'end_map': depth -= 1 ``` -------------------------------- ### Get ijson Backend and Version Info Source: https://github.com/icrar/ijson/blob/master/_autodocs/06-backends.md Retrieve and print the name of the currently selected ijson backend, the ijson library version, and the capabilities of the selected backend. This helps in understanding the environment and available features. ```python import ijson print(f"Backend: {ijson.backend_name}") print(f"ijson version: {ijson.__version__}") backend = ijson.get_backend(ijson.backend_name) print(f"Capabilities: {backend.capabilities.__dict__}") ``` -------------------------------- ### Check Backend Capabilities at Runtime Source: https://github.com/icrar/ijson/blob/master/_autodocs/03-configuration.md This Python snippet demonstrates how to get the current IJSON backend and check its capabilities, such as support for C-style comments or multiple top-level values. It also shows how to conditionally print messages based on these capabilities. ```python import ijson backend = ijson.get_backend(ijson.backend_name) print(f"Backend: {ijson.backend_name}") print(f"Supports comments: {backend.capabilities.c_comments}") print(f"Supports multiple values: {backend.capabilities.multiple_values}") # Check before using an option if not backend.capabilities.c_comments: print("This backend does not support allow_comments=True") ``` -------------------------------- ### Get Default Backend Name Source: https://github.com/icrar/ijson/blob/master/_autodocs/06-backends.md Prints the name of the best available backend automatically selected by ijson. This is useful for verifying which backend is currently in use. ```python import ijson # Uses best available backend print(ijson.backend_name) # e.g., "yajl2_c" ``` -------------------------------- ### Parsing JSON array start and end Source: https://github.com/icrar/ijson/blob/master/_autodocs/07-events.md Demonstrates capturing ('start_array', None) and ('end_array', None) events for JSON array delimiters, along with nested structures. ```python for event_type, value in ijson.basic_parse(b'[1,2,[3,4]]'): if event_type == 'start_array': print("Array start") elif event_type == 'number': print(f" Item: {value}") elif event_type == 'end_array': print("Array end") # Output: # Array start # Item: 1 # Item: 2 # Array start # Item: 3 # Item: 4 # Array end # Array end ``` -------------------------------- ### Visualize ijson.dump output from stdin Source: https://github.com/icrar/ijson/blob/master/README.rst Use the `ijson.dump` module as a command-line tool to parse JSON from standard input and visualize the parsing events. This example shows the output for the 'parse' method. ```bash $ echo '{"A": 0, "B": [1, 2, 3, 4]}' | python -m ijson.dump -m parse ``` -------------------------------- ### Catching IncompleteJSONError for Truncated Input Source: https://github.com/icrar/ijson/blob/master/_autodocs/05-errors.md This example demonstrates how to catch `IncompleteJSONError`, which is raised when the JSON input is truncated or ends unexpectedly. It's crucial for handling network interruptions or incomplete file reads. ```python import ijson try: # Truncated JSON for item in ijson.items(b'{"incomplete": "valu', 'item'): pass except ijson.IncompleteJSONError as e: print(f"Input truncated: {e}") ``` -------------------------------- ### Example Event Sequence for JSON Object Source: https://github.com/icrar/ijson/blob/master/_autodocs/07-events.md Shows the precise sequence of ijson events emitted when parsing a simple JSON object `{"key": {"nested": "value"}}`, illustrating timing relative to JSON structure. ```python ('', 'start_map', None) # After { ('', 'map_key', 'key') # After "key" ('key', 'start_map', None) # After second { ('key', 'map_key', 'nested') # After "nested" ('key.nested', 'string', 'value') # After "value" is completely parsed ('key', 'end_map', None) # After } ('', 'end_map', None) # After final } ``` -------------------------------- ### Get Specific Backend with ijson.get_backend Source: https://github.com/icrar/ijson/blob/master/README.rst Use ijson.get_backend to retrieve a specific backend implementation by its name. This is useful when you need to programmatically select a backend other than the default. ```python backend = ijson.get_backend('yajl2_c') for item in backend.items(...): # ... ``` -------------------------------- ### Using ijson Items Coroutine Source: https://github.com/icrar/ijson/blob/master/_autodocs/04-types.md Example demonstrating how to use `ijson.items_coro` to parse JSON items into a target list. Ensure the parser is closed after sending all data. ```python import ijson # Create pipeline target = ijson.sendable_list() coro = ijson.items_coro(target, 'items.item') # Push data with open('data.json', 'rb') as f: for chunk in iter(lambda: f.read(8192), b''): coro.send(chunk) # Cleanup coro.close() # Process results for item in target: print(item) ``` -------------------------------- ### React to Events in Real-Time Source: https://github.com/icrar/ijson/blob/master/_autodocs/INDEX.md Use ijson.parse to iterate over individual JSON events (start map, end map, value, etc.) and react to specific prefixes in real-time. This allows for granular control and processing as data is parsed. ```python import ijson for prefix, event_type, value in ijson.parse(source): if prefix == 'users.item.name': print(f"User: {value}") ``` -------------------------------- ### Get Specific Backend Programmatically Source: https://github.com/icrar/ijson/blob/master/_autodocs/06-backends.md Retrieves a specific backend implementation by its name using `ijson.get_backend()`. Includes error handling for `ImportError` if the requested backend is not available, falling back to the Python backend. ```python import ijson backend = ijson.get_backend('yajl2_c') # Catch ImportError if backend unavailable try: backend = ijson.get_backend('yajl2_c') except ImportError: backend = ijson.get_backend('python') for item in backend.items(data, 'prefix'): print(item) ``` -------------------------------- ### Compare ijson Backends Source: https://github.com/icrar/ijson/blob/master/_autodocs/06-backends.md Compare the performance of different ijson backends using the benchmark tool. Specify the data file, item prefix, backends to compare, and the number of iterations. ```bash python -m ijson.benchmark data.json -m items -p 'data.item' \ --backends yajl2_c yajl2_cffi python \ --iterations 5 ``` -------------------------------- ### Print All Supported Backend Names Source: https://github.com/icrar/ijson/blob/master/_autodocs/02-main-api.md Display a tuple of all supported backend names for ijson, ordered by descending speed. This provides an overview of available parsing options. ```python import ijson print(ijson.ALL_BACKENDS) # ('yajl2_c', 'yajl2_cffi', 'yajl2', 'yajl', 'python') ``` -------------------------------- ### Graceful Degradation with Fallback Backend Source: https://github.com/icrar/ijson/blob/master/_autodocs/05-errors.md This snippet demonstrates how to attempt using a faster C backend (yajl2_c) and gracefully fall back to a pure Python implementation if the C backend is not available due to an ImportError. ```python import ijson # Try fast C backend, fall back to pure Python try: backend = ijson.get_backend('yajl2_c') except ImportError: backend = ijson.get_backend('python') with open('data.json', 'rb') as f: for item in backend.items(f, 'data.item'): process(item) ``` -------------------------------- ### Custom Object Container Source: https://github.com/icrar/ijson/blob/master/_autodocs/00-TABLE-OF-CONTENTS.md Specifies a custom class to be used for representing JSON objects (maps). For example, using OrderedDict to preserve key order. ```python from collections import OrderedDict ijson.items(f, 'items.item', map_type=OrderedDict) ``` -------------------------------- ### Find Configuration Options for use_float Source: https://github.com/icrar/ijson/blob/master/_autodocs/README.md Find configuration options, such as using Decimal instead of float, via the INDEX.md reference. The use_float option defaults to True. ```python # Want to use Decimal instead of float? ijson.items(f, 'data.item', use_float=False) # False is default # See [03-configuration.md](03-configuration.md) - "use_float" section ``` -------------------------------- ### Accessing Backend Capabilities in ijson Source: https://github.com/icrar/ijson/blob/master/_autodocs/04-types.md Demonstrates how to retrieve and check backend capabilities, such as comment support or multiple value parsing. This allows for conditional logic based on the underlying parser's features. ```python import ijson backend = ijson.get_backend(ijson.backend_name) caps = backend.capabilities if caps.c_comments: print("Comments supported") if not caps.multiple_values: print("Cannot parse JSONL") ``` -------------------------------- ### Run ijson Benchmark Source: https://github.com/icrar/ijson/blob/master/README.rst Use the ijson.benchmark module to benchmark parsing performance on a JSON file. Specify input file, backend, and number of iterations. ```bash python -m ijson.benchmark my/json/file.json -m items -p values.item ``` -------------------------------- ### Basic JSON Parsing with basic_parse Source: https://github.com/icrar/ijson/blob/master/_autodocs/02-main-api.md Use basic_parse to get raw parsing events without prefix information. This is useful for low-level processing of JSON streams. ```python import ijson with open('data.json', 'rb') as f: for event_type, value in ijson.basic_parse(f): if event_type == 'map_key': print(f"Key: {value}") elif event_type == 'number': print(f"Number: {value}") ``` -------------------------------- ### Transform Event Values in Python Source: https://github.com/icrar/ijson/blob/master/_autodocs/08-usage-patterns.md Modify values as they are parsed by transforming event data. This example converts decimal prices to cents (integers) and requires 'ijson' and 'decimal'. ```python import ijson import decimal def normalize_prices(parse_events): """Convert all decimal prices to cents (integers).""" for prefix, event_type, value in parse_events: if event_type == 'number' and 'price' in prefix: # Convert to cents value = int(value * 100) if isinstance(value, (int, decimal.Decimal)) else value yield prefix, event_type, value with open('data.json', 'rb') as f: events = ijson.parse(f) transformed = normalize_prices(events) for item in ijson.items(transformed, 'products.item'): print(f"{item['name']}: {item['price']} cents") ``` -------------------------------- ### Backend Reference Source: https://github.com/icrar/ijson/blob/master/_autodocs/README.md Overview of ijson's backends, including selection methods, specific backend details (YAJL, Python), and performance comparisons. ```APIDOC ## Backend Overview and Selection **Description**: Explains the concept of backends in ijson and how to select them. ## Automatic vs. Manual Selection **Description**: Details the differences and use cases for automatic and manual backend selection. ## YAJL 2.x Backends ### `yajl2_c`, `yajl2_cffi`, `yajl2` **Description**: Information specific to the YAJL 2.x C-based backends. ## Python Backend **Description**: Details regarding the pure Python backend implementation. ## Capability Matrix **Description**: A matrix comparing the capabilities of different backends. ## Implementation Details **Description**: Technical details about the implementation of various backends. ## Performance Comparison **Description**: A comparison of the performance characteristics of different backends. ## Backend Selection Guide **Description**: Guidance on choosing the most appropriate backend for specific needs. ## YAJL Library Loading **Description**: Information on how the YAJL library is loaded and managed. ``` -------------------------------- ### Basic JSON Parsing with ijson.basic_parse Source: https://github.com/icrar/ijson/blob/master/_autodocs/README.md Use ijson.basic_parse to get raw events from a JSON source. This function returns tuples of (event_type, value) without path context. ```python ijson.basic_parse(source, ...) ``` -------------------------------- ### Filter Events with Python Generator Source: https://github.com/icrar/ijson/blob/master/_autodocs/07-events.md A Python generator function to filter ijson events based on their prefix. It yields events that do not start with an underscore, useful for skipping private fields. ```python import ijson def filter_events(parse_events): """Filter out events at certain paths.""" for prefix, event_type, value in parse_events: if not prefix.startswith('_'): # Skip "private" fields yield prefix, event_type, value ``` -------------------------------- ### Configuration Reference Source: https://github.com/icrar/ijson/blob/master/_autodocs/README.md Details on configuration options for customizing ijson's behavior, including number types, JSONL support, and environment variables. ```APIDOC ## Configuration Options ### `use_float` **Description**: Controls whether numbers are parsed as floats or other numeric types. ### `multiple_values` **Description**: Enables support for parsing multiple JSON values (JSONL format). ### `allow_comments` **Description**: Allows parsing of non-standard JSON with comments. ### `buf_size` **Description**: Configures the buffer size for I/O operations to optimize performance. ### `map_type` **Description**: Allows customization of the container type used for JSON objects. ## Environment Variables ### `IJSON_BACKEND` **Description**: Specifies the backend to use via an environment variable. ### `YAJL_DLL` **Description**: Path to the YAJL library DLL, used for specific backends. ## Backend Capability Matrix **Description**: A matrix detailing the capabilities of different available backends. ## Configuration Examples **Description**: Illustrative examples demonstrating how to configure ijson for various use cases. ``` -------------------------------- ### Custom Event Processing with Filtering Source: https://github.com/icrar/ijson/blob/master/_autodocs/INDEX.md Implement custom logic to filter or transform JSON parsing events before processing them further. This example shows how to skip private fields based on their prefix. ```python import ijson def filter_events(parse_events): for prefix, event_type, value in parse_events: if '_' not in prefix: # Skip private fields yield prefix, event_type, value with open('data.json', 'rb') as f: events = ijson.parse(f) filtered = filter_events(events) for item in ijson.items(filtered, 'data.item'): process(item) ``` -------------------------------- ### Force Pure Python Backend Source: https://github.com/icrar/ijson/blob/master/_autodocs/03-configuration.md Use this to force the pure Python backend, which has no compiled dependencies. This is useful for environments where compilation is not possible or desired. ```bash # Force pure Python backend (no compiled dependencies) export IJSON_BACKEND=python python script.py ``` -------------------------------- ### Run ijson Benchmark Source: https://github.com/icrar/ijson/blob/master/_autodocs/06-backends.md Execute ijson's built-in benchmark to measure parsing performance. Specify the data file, the object to parse, and the prefix for items. ```bash python -m ijson.benchmark data.json -m items -p 'data.item' ``` -------------------------------- ### Count occurrences of 'name' keys with basic_parse Source: https://github.com/icrar/ijson/blob/master/README.rst Use the `basic_parse` function to react to individual events without prefix calculation. This example counts the number of times a 'map_key' with the value 'name' appears. ```python import ijson events = ijson.basic_parse(urlopen('http://.../')) num_names = sum(1 for event, value in events if event == 'map_key' and value == 'name') ``` -------------------------------- ### Utilities Source: https://github.com/icrar/ijson/blob/master/_autodocs/README.md Offers utility functions for backend loading, adapting iterables, and decorating generator coroutines. ```APIDOC ## Utilities ### Description Offers utility functions for backend loading, adapting iterables, and decorating generator coroutines. ### Functions - `ijson.get_backend(name)`: Loads a specific backend by name. - `ijson.from_iter(byte_iter)`: Adapts an iterable of bytes to a file-like object. - `ijson.coroutine(func)`: A decorator for generator coroutines. ### Method N/A (Python functions) ### Endpoint N/A (Python functions) ### Parameters N/A (Refer to specific function documentation for details) ### Request Example N/A ### Response N/A ``` -------------------------------- ### Set Backend via Environment Variable Source: https://github.com/icrar/ijson/blob/master/_autodocs/00-TABLE-OF-CONTENTS.md Configures the ijson backend by setting the IJSON_BACKEND environment variable before running the Python script. This allows for flexible backend selection without code modification. ```bash export IJSON_BACKEND=python python script.py ``` -------------------------------- ### BackendCapabilities Class Source: https://github.com/icrar/ijson/blob/master/_autodocs/INDEX.md Exposes supported features of an ijson backend. Check attributes like comment support, multiple value handling, and integer parsing capabilities. ```python class BackendCapabilities: """Exposes what features a backend supports.""" def __init__(self, c_comments=False, multiple_values=False, invalid_leading_zeros_detection=False, incomplete_json_tokens_detection=False, int64=False): self.c_comments = c_comments self.multiple_values = multiple_values self.invalid_leading_zeros_detection = invalid_leading_zeros_detection self.incomplete_json_tokens_detection = incomplete_json_tokens_detection self.int64 = int64 ``` -------------------------------- ### Force YAJL 2 with CFFI Backend Source: https://github.com/icrar/ijson/blob/master/_autodocs/03-configuration.md Use this to force the YAJL 2 backend with CFFI, which provides portable C bindings. This is a good option for performance when C extensions are available. ```bash # Force YAJL 2 with CFFI (portable C bindings) export IJSON_BACKEND=yajl2_cffi python script.py ``` -------------------------------- ### Process JSON events with ijson.parse Source: https://github.com/icrar/ijson/blob/master/README.rst Use the `parse` function for lower-level event handling without constructing full Python objects. This example writes XML-like tags based on JSON structure and events. ```python import ijson parser = ijson.parse(urlopen('http://.../')) stream.write('') for prefix, event, value in parser: if (prefix, event) == ('earth', 'map_key'): stream.write('<%s>' % value) continent = value elif prefix.endswith('.name'): stream.write('' % value) elif (prefix, event) == ('earth.%s' % continent, 'end_map'): stream.write('' % continent) stream.write('') ``` -------------------------------- ### Check ijson Backend Capabilities Source: https://github.com/icrar/ijson/blob/master/_autodocs/05-errors.md Inspect the capabilities of the currently configured ijson backend. This is useful for understanding performance characteristics and feature support, such as comments or handling multiple JSON values. ```python import ijson backend = ijson.get_backend(ijson.backend_name) print(f"Backend: {ijson.backend_name}") print(f" Comments: {backend.capabilities.c_comments}") print(f" Multiple values: {backend.capabilities.multiple_values}") print(f" Invalid zero detection: {backend.capabilities.invalid_leading_zeros_detection}") print(f" Incomplete token detection: {backend.capabilities.incomplete_json_tokens_detection}") print(f" 64-bit int (use_float=True): {backend.capabilities.int64}") ``` -------------------------------- ### Extract names of European places using kvitems Source: https://github.com/icrar/ijson/blob/master/README.rst Use the `kvitems` function to iterate over object members rather than entire objects, useful when objects are too large. This example extracts names from European places. ```python import ijson f = urlopen('http://.../') european_places = ijson.kvitems(f, 'earth.europe.item') names = (v for k, v in european_places if k == 'name') for name in names: do_something_with(name) ``` -------------------------------- ### Explicitly Use Python Backend Source: https://github.com/icrar/ijson/blob/master/_autodocs/06-backends.md Imports the Python backend directly to ensure its usage. This is an alternative to using the environment variable for programmatic control. ```python # Use Python backend explicitly import ijson.backends.python as ijson for item in ijson.items(data, 'prefix'): print(item) ``` -------------------------------- ### Benchmark ijson Buffer Size Source: https://github.com/icrar/ijson/blob/master/_autodocs/08-usage-patterns.md Tests different buffer sizes for ijson parsing to find the optimal setting for your workload. Run this with your typical JSON file and prefix. ```python import ijson import time def benchmark_buffer_size(file_path, prefix, sizes=[4096, 16384, 65536, 262144]): """Test different buffer sizes.""" for buf_size in sizes: start = time.time() count = 0 with open(file_path, 'rb') as f: for item in ijson.items(f, prefix, buf_size=buf_size): count += 1 elapsed = time.time() - start print(f"buf_size={buf_size}: {count} items in {elapsed:.2f}s") benchmark_buffer_size('large.json', 'data.item') ``` -------------------------------- ### Python Backend Metadata Source: https://github.com/icrar/ijson/blob/master/_autodocs/06-backends.md Provides metadata about the backend, including its name and supported capabilities. ```python backend = "yajl2_c" # Backend name string backend_name = "yajl2_c" # Same as above capabilities = BackendCapabilities() # Capability flags ``` -------------------------------- ### Explicitly Select Parsing Backend Source: https://github.com/icrar/ijson/blob/master/_autodocs/03-configuration.md Select a specific ijson backend, such as the fast `yajl2_c` extension, or fall back to the pure Python implementation if the C extension is unavailable. ```python import ijson # Ensure fastest C backend or fall back to Python try: backend = ijson.get_backend('yajl2_c') except ImportError: backend = ijson.get_backend('python') with open('data.json', 'rb') as f: for item in backend.items(f, 'data.item'): process(item) ``` -------------------------------- ### Unified Entry Points Source: https://github.com/icrar/ijson/blob/master/_autodocs/06-backends.md Unified functions that auto-detect the source type and delegate to the appropriate parsing function. ```APIDOC ## Unified entry points: ```python def basic_parse(source, buf_size=65536, **config): """Auto-detects source type and delegates to appropriate function.""" def parse(source, buf_size=65536, **config): def items(source, prefix, map_type=None, buf_size=65536, **config): def kvitems(source, prefix, map_type=None, buf_size=65536, **config): ``` ``` -------------------------------- ### Force Python Backend Source: https://github.com/icrar/ijson/blob/master/_autodocs/00-TABLE-OF-CONTENTS.md Explicitly selects the pure Python backend for parsing. This is useful for environments where C extensions are not available or desired. ```python backend = ijson.get_backend('python') ``` -------------------------------- ### kvitems_async Source: https://github.com/icrar/ijson/blob/master/_autodocs/02-main-api.md Asynchronous equivalent of `kvitems`. Accepts async file-like objects and returns async iterators. ```APIDOC ## `kvitems_async(f, prefix, map_type=None, buf_size=65536, **config)` ### Description Async equivalent of `kvitems`. Accepts async file-like objects (with async `read` method) and returns async iterators usable with `async for`. ### Parameters #### Path Parameters - `f` (async file-like object) - Required - JSON input or `parse` event generator - `prefix` (str) - Required - Dot-separated path pointing to a JSON object (e.g., `"item.properties"`) #### Query Parameters - `map_type` (dict-like class) - Optional - Container class for JSON objects, defaults to `dict` - `buf_size` (int) - Optional - Bytes to read per I/O operation, defaults to `65536` - `use_float` (bool) - Optional - Return floating-point numbers as `float` instead of `Decimal`, defaults to `False` - `multiple_values` (bool) - Optional - Allow multiple top-level JSON values, defaults to `False` - `allow_comments` (bool) - Optional - Allow C-style comments, defaults to `False` ### Returns Async generator yielding `(key, value)` tuples for each member of the object at the prefix. ### Example ```python import ijson import asyncio async def process(): f = await async_urlopen('http://.../') async for key, value in ijson.kvitems_async(f, 'data.item'): print(f"{key}: {value}") asyncio.run(process()) ``` ``` -------------------------------- ### IJSON File Dependencies Source: https://github.com/icrar/ijson/blob/master/_autodocs/MANIFEST.md Visual representation of the file dependencies within the IJSON project, showing the relationships between different documentation files. ```text START → 00-TABLE-OF-CONTENTS.md OR README.md ↓ ├─→ INDEX.md (master reference) │ ├─→ 01-overview.md (project intro) │ ├─→ 02-main-api.md ⭐ MAIN REFERENCE │ ├─→ 03-configuration.md │ ├─→ 04-types.md │ └─→ 05-errors.md │ ├─→ 06-backends.md │ └─→ 03-configuration.md │ ├─→ 07-events.md │ └─→ 04-types.md │ └─→ 08-usage-patterns.md └─→ 02-main-api.md ``` -------------------------------- ### Asynchronous HTTP Streaming with httpx Source: https://github.com/icrar/ijson/blob/master/_autodocs/08-usage-patterns.md Handles asynchronous HTTP streaming using the httpx library. `from_iter` automatically detects async iterables, and `ijson.items_async` is used for async iteration. ```python import ijson import httpx async def process_users(): async with httpx.AsyncClient() as client: async with client.stream('GET', 'http://api.example.com/users') as resp: resp.raise_for_status() # from_iter detects async iterable automatically f = ijson.from_iter(resp.aiter_bytes()) async for user in ijson.items_async(f, 'data.item'): await save_user(user) asyncio.run(process_users()) ``` -------------------------------- ### Dynamically Choose the Fastest ijson Backend Source: https://github.com/icrar/ijson/blob/master/_autodocs/08-usage-patterns.md Select the most performant JSON parsing backend available on the system, with a fallback mechanism. This function iterates through all known ijson backends, attempting to import and use the first one that is successfully loaded. If no backends are available, it raises a RuntimeError. ```python import ijson def get_best_backend(): """Get the best available backend.""" for backend_name in ijson.ALL_BACKENDS: try: return ijson.get_backend(backend_name) except ImportError: continue raise RuntimeError("No backends available") backend = get_best_backend() print(f"Using {backend.backend_name} backend") with open('data.json', 'rb') as f: for item in backend.items(f, 'items.item'): process(item) ``` -------------------------------- ### Backend Selection Source: https://github.com/icrar/ijson/blob/master/_autodocs/02-main-api.md Information about selecting and using different backends for JSON parsing within IJSON. ```APIDOC ### `backend_name` Module-level constant: name of the currently active backend (`"yajl2_c"`, `"yajl2_cffi"`, `"yajl2"`, `"yajl"`, or `"python"`). **Source:** `ijson/__init__.py` ```python import ijson print(ijson.backend_name) # e.g., "yajl2_c" ``` ### `get_backend(name)` Dynamically import and return a specific backend module by name. **Source:** `ijson/__init__.py` **Parameters:** | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `name` | str | ✓ | Backend name: `"yajl2_c"`, `"yajl2_cffi"`, `"yajl2"`, `"yajl"`, or `"python"` | **Returns:** Backend module with `basic_parse`, `parse`, `items`, `kvitems` functions **Throws:** `ImportError` if backend unavailable **Example:** ```python import ijson # Force use of Python backend backend = ijson.get_backend('python') for item in backend.items(json_source, 'data.item'): print(item) ``` ### `ALL_BACKENDS` Module-level constant: tuple of all supported backend names in descending speed order. **Source:** `ijson/__init__.py` ```python import ijson print(ijson.ALL_BACKENDS) # ('yajl2_c', 'yajl2_cffi', 'yajl2', 'yajl', 'python') ``` ### Backend Selection Logic 1. If environment variable `IJSON_BACKEND` is set, its value is used 2. Otherwise, backends are tried in order (`yajl2_c`, `yajl2_cffi`, `yajl2`, `yajl`, `python`) 3. First available backend is selected 4. If no backend is available, `ImportError` is raised ``` -------------------------------- ### Basic JSON Events Source: https://github.com/icrar/ijson/blob/master/_autodocs/00-TABLE-OF-CONTENTS.md Illustrates the basic event types generated by ijson for different JSON values and structures. ```python ('null', None) # JSON null ('boolean', True) # JSON true ('number', 42) # JSON 42 ('string', 'hello') # JSON "hello" ('map_key', 'key') # Object key ('start_map', None) # { ('end_map', None) # } ('start_array', None) # [ ('end_array', None) # ] ``` -------------------------------- ### Load Specific Backend with ijson.get_backend Source: https://github.com/icrar/ijson/blob/master/_autodocs/README.md Load a specific ijson backend by its name using the ijson.get_backend() utility function. ```python ijson.get_backend(name) ``` -------------------------------- ### Python Backend Unified Entry Points Source: https://github.com/icrar/ijson/blob/master/_autodocs/06-backends.md These functions provide a unified interface for parsing JSON, automatically detecting the source type and delegating to the appropriate parsing function. ```python def basic_parse(source, buf_size=65536, **config): """Auto-detects source type and delegates to appropriate function.""" def parse(source, buf_size=65536, **config): def items(source, prefix, map_type=None, buf_size=65536, **config): def kvitems(source, prefix, map_type=None, buf_size=65536, **config): ``` -------------------------------- ### Compare ijson Decimal vs. Float Parsing Speed Source: https://github.com/icrar/ijson/blob/master/_autodocs/08-usage-patterns.md Compares the performance of parsing numbers as precise Decimals versus faster, less precise floats using the `use_float` option. Useful for identifying performance bottlenecks related to number handling. ```python import ijson import time import decimal def compare_number_handling(file_path, prefix): """Compare decimal vs float parsing speed.""" # Decimal (slower, precise) start = time.time() count_decimal = 0 with open(file_path, 'rb') as f: for item in ijson.items(f, prefix, use_float=False): if isinstance(item.get('price'), decimal.Decimal): count_decimal += 1 time_decimal = time.time() - start # Float (faster, less precise) start = time.time() count_float = 0 with open(file_path, 'rb') as f: for item in ijson.items(f, prefix, use_float=True): if isinstance(item.get('price'), float): count_float += 1 time_float = time.time() - start print(f"Decimal: {time_decimal:.2f}s") print(f"Float: {time_float:.2f}s (speedup: {time_decimal/time_float:.1f}x)") compare_number_handling('prices.json', 'products.item') ``` -------------------------------- ### ObjectBuilder Class Source: https://github.com/icrar/ijson/blob/master/_autodocs/INDEX.md Constructs Python objects from parser events. Initialize with an optional custom dictionary type. ```python class ObjectBuilder: """Constructs Python objects from parser events.""" def __init__(self, map_type=None): """Initialize with optional custom dict type.""" self.map_type = map_type self.value = None def event(self, event_type, value): """Process a parser event.""" if event_type == 'start_map': self.value = (self.map_type or dict)() elif event_type == 'end_map': pass elif event_type == 'start_array': self.value = [] elif event_type == 'end_array': pass elif event_type == 'map_key': self.value = value elif event_type == 'string': self.value = value elif event_type == 'number': self.value = value elif event_type == 'boolean': self.value = value elif event_type == 'null': self.value = None else: raise ValueError('Unknown event type: %s' % event_type) ``` -------------------------------- ### Identify Fastest Backend (yajl2_c) Source: https://github.com/icrar/ijson/blob/master/_autodocs/README.md Determine the fastest backend for ijson, which is yajl2_c due to its C extension. Refer to 06-backends.md for backend overview. ```python # Which backend is fastest? # Answer: yajl2_c (C extension) # See [06-backends.md](06-backends.md) - "Backend Overview" ``` -------------------------------- ### parse(source, buf_size=65536, **config) Source: https://github.com/icrar/ijson/blob/master/_autodocs/02-main-api.md Yields parsing events with prefix information indicating position in the JSON tree. This is useful for navigating and extracting specific parts of a JSON document. ```APIDOC ## parse(source, buf_size=65536, **config) ### Description Yields parsing events with prefix information indicating position in the JSON tree. This is useful for navigating and extracting specific parts of a JSON document. ### Parameters #### Source - **source** (bytes, str, file-like, iterable, or generator) - Required - JSON input or `basic_parse` event generator #### Optional Parameters - **buf_size** (int) - Optional - Default: 65536 - Bytes to read per I/O operation (ignored if source is a generator) - **use_float** (bool) - Optional - Default: False - Return floating-point numbers as `float` instead of `Decimal` - **multiple_values** (bool) - Optional - Default: False - Allow multiple top-level JSON values - **allow_comments** (bool) - Optional - Default: False - Allow C-style comments ### Returns Generator yielding `(prefix, event_type, value)` tuples ### Prefix format Dot-separated path from document root: - Empty string `""` for top-level events - `"key"` for object member named "key" - `"array.item"` for array elements - `"object.array.item.key"` for nested structures ### Example ```python import ijson with open('data.json', 'rb') as f: for prefix, event_type, value in ijson.parse(f): if event_type == 'string' and prefix.endswith('.name'): print(f"Name found: {value}") ``` ``` -------------------------------- ### Handling ijson Exceptions Source: https://github.com/icrar/ijson/blob/master/_autodocs/04-types.md Provides a try-except block demonstrating how to catch specific ijson exceptions like `IncompleteJSONError` and `JSONError`, as well as standard `ValueError` for configuration issues. ```python try: for item in ijson.items(data, prefix): process(item) except ijson.IncompleteJSONError: # Truncated input handle_truncation() except ijson.JSONError: # Syntax error handle_syntax_error() except ValueError: # Invalid configuration handle_config_error() ``` -------------------------------- ### Print Active Backend Name Source: https://github.com/icrar/ijson/blob/master/_autodocs/02-main-api.md Display the name of the currently active ijson backend. This can be useful for debugging or verifying backend selection. ```python import ijson print(ijson.backend_name) # e.g., "yajl2_c" ``` -------------------------------- ### AiterReader Class Source: https://github.com/icrar/ijson/blob/master/_autodocs/INDEX.md An async file-like adapter for asynchronous byte iterables. Use this for adapting async byte streams in an async context. ```python class AiterReader: """Async file-like adapter for async byte iterables.""" def __init__(self, aiterable): self.ainterable = aiterable self.buffer = b'' async def read(self, size=-1): if size == -1: data = self.buffer async for chunk in self.ainterable: data += chunk return data else: while len(self.buffer) < size: try: self.buffer += await anext(self.ainterable) except StopAsyncIteration: break result = self.buffer[:size] self.buffer = self.buffer[size:] return result async def close(self): pass ``` -------------------------------- ### ObjectBuilder Initialization Source: https://github.com/icrar/ijson/blob/master/_autodocs/04-types.md Initializes the ObjectBuilder with an optional custom map type for JSON objects. ```python def __init__(self, map_type=None): """Initialize builder with optional custom map type.""" ``` -------------------------------- ### Utility Functions Source: https://github.com/icrar/ijson/blob/master/_autodocs/INDEX.md Helper functions for adapting iterables, creating coroutines, and accumulating results. ```APIDOC ## ijson.from_iter ### Description Adapts a byte iterable to behave like a file-like object. ### Function Signature ```python ijson.from_iter(byte_iter) ``` ### Parameters - **byte_iter**: An iterable yielding bytes. ## ijson.coroutine ### Description A decorator for converting generator-based coroutines. ### Function Signature ```python ijson.coroutine(func) ``` ### Parameters - **func**: The generator function to decorate. ## ijson.sendable_list ### Description Provides a list-based accumulator for results, suitable for coroutines. ### Function Signature ```python ijson.sendable_list() ``` ``` -------------------------------- ### Force Python Backend via Environment Variable Source: https://github.com/icrar/ijson/blob/master/_autodocs/06-backends.md Sets the IJSON_BACKEND environment variable to 'python' to force the use of the pure Python implementation. This is useful for testing or when other backends are unavailable. ```bash # Force Python backend export IJSON_BACKEND=python python script.py ``` -------------------------------- ### Backend and Utility Functions Source: https://github.com/icrar/ijson/blob/master/_autodocs/INDEX.md Provides functions for interacting with ijson's backend implementations and utility functions for adapting iterables and managing coroutines. ```python ijson.get_backend(name) # Get specific backend by name ijson.backend_name # Current backend name (constant) ijson.ALL_BACKENDS # Tuple of all available backends ``` ```python ijson.from_iter(byte_iter) # Adapt byte iterable to file-like ijson.coroutine(func) # Decorator for generator coroutines ijson.sendable_list() # List-based result accumulator ``` -------------------------------- ### Python Backend Source: https://github.com/icrar/ijson/blob/master/_autodocs/06-backends.md The pure Python backend for ijson. It has no external dependencies and is portable but is the slowest implementation. ```APIDOC ## python **Source file:** `src/ijson/backends/python.py` **Requirements:** None (pure Python, uses only stdlib) **Advantages:** - No external dependencies - Works with PyPy - Portable to any Python environment - Good fallback when C libraries unavailable **Disadvantages:** - Slowest implementation - Does not support C-style comments (`allow_comments=False` always) ``` -------------------------------- ### Configure I/O Buffer Size with buf_size Source: https://github.com/icrar/ijson/blob/master/_autodocs/03-configuration.md Adjust the `buf_size` parameter to control the buffer size for I/O operations. Smaller buffers use less memory, while larger buffers can improve performance on fast I/O devices. This is ignored for byte/string/iterable sources. ```python import ijson # Small buffer for memory-constrained environments with open('huge.json', 'rb') as f: for item in ijson.items(f, 'data.item', buf_size=4096): process(item) # Large buffer for SSD/network streams with open('data.json', 'rb') as f: for item in ijson.items(f, 'data.item', buf_size=262144): process(item) ``` -------------------------------- ### IterReader Class Source: https://github.com/icrar/ijson/blob/master/_autodocs/INDEX.md Provides a file-like adapter for byte iterables. Use this to adapt iterable byte streams into a format readable by ijson. ```python class IterReader: """File-like adapter for byte iterables.""" def __init__(self, iterable): self.iterable = iterable self.buffer = b'' def read(self, size=-1): if size == -1: return self.buffer + b''.join(self.iterable) else: while len(self.buffer) < size: try: self.buffer += next(self.iterable) except StopIteration: break result = self.buffer[:size] self.buffer = self.buffer[size:] return result def close(self): pass ``` -------------------------------- ### Using ObjectBuilder for Incremental JSON Parsing Source: https://github.com/icrar/ijson/blob/master/_autodocs/02-main-api.md Demonstrates how to use `ObjectBuilder` to incrementally construct Python objects from JSON events. This is useful for processing large JSON files without loading the entire structure into memory. ```python from ijson.common import ObjectBuilder from ijson import basic_parse builder = ObjectBuilder() with open('data.json', 'rb') as f: for event_type, value in basic_parse(f): builder.event(event_type, value) print(builder.value) # Constructed object ```