Skip to main content

jload

A simple utility to load and save lists of dictionaries from/to JSON and JSONL files, with automatic format detection.

Installation

pip install jload

Usage

from jload import jload, jsave

# File extension doesn't matter - format is auto-detected between json and jsonl
data = jload('path/to/any_file')

# List of dictionaries to save
data = [{'name': 'Alice', 'age': 30}, {'name': 'Bob', 'age': 25}]

# Save as JSONL
jsave(data, 'output.jsonl', format='jsonl')

# Auto-detect format based on file extension
jsave(data, 'output.jsonl')  # Will be saved as JSONL
jsave(data, 'output.json')   # Will be saved as JSON, with auto indent

# Append a single entry using the append parameter
entry = {'name': 'Charlie', 'age': 35}

# Append to a JSON file (will be added to the array)
jsave(entry, 'output.json', append=True)

# Append to a JSONL file (will add a new line)
jsave(entry, 'output.jsonl', append=True)

Features

  • Format Auto-detection:
    • When loading: Automatically detects if a file contains JSON or JSONL (JSON Lines) format
    • When saving: Determines format based on file extension (.jsonl/.ndjson for JSONL, anything else for JSON)
  • Flexible Parsing:
    • Handles JSON arrays of dictionaries
    • Handles single JSON objects (returns as a list with one dictionary)
    • Handles JSONL with one JSON object per line
  • Error Handling: Provides meaningful error messages for invalid files or formats
  • Lightweight: No dependencies beyond Python's standard library

Function Details

jload

def jload(file_path: str) -> list[dict]:
    """
    Loads a list of dictionaries from a file, attempting to auto-detect
    if it's a single JSON array/object or JSONL (JSON Lines).
    The function prioritizes content analysis over file extension.

    Args:
        file_path (str): The path to the data file.

    Returns:
        list[dict]: A list of dictionaries loaded from the file.
                    - If the file content is a JSON array of objects, it's returned as is.
                    - If the file content is a single JSON object, it's returned as a list
                      containing that single object.
                    - If the file content appears to be JSONL, each line that is a valid
                      JSON object is included in the returned list.
                    - Returns an empty list if the file is empty.

    Raises:
        FileNotFoundError: If the specified file_path does not exist.
        ValueError: If the file content cannot be interpreted as either
                    a JSON array/object or JSONL format.
    """

jsave

def jsave(data, file_path: str, format: str = 'auto', indent: int = 2, append: bool = False) -> None:
    """
    Saves data to a file in either JSON or JSONL format.

    Args:
        data: The data to save.
            - For 'json' format: Can be any JSON-serializable data (dict, list, str, int, etc.)
            - For 'jsonl' format: Must be a list of dictionaries if append=False
                                 Must be a dictionary if append=True
        file_path (str): The path where the file will be saved.
        format (str, optional): The format to save in. Options:
            - 'auto': Determine format based on file extension (.jsonl/.ndjson for JSONL, anything else for JSON)
            - 'json': Save as a JSON document
            - 'jsonl': Save as JSONL (one JSON object per line)
            Defaults to 'auto'.
        indent (int, optional): Number of spaces for indentation in JSON format.
            Only applies to 'json' format, ignored for 'jsonl'. Defaults to 2.
        append (bool, optional): If True, appends data to the existing file instead of overwriting.
            - For 'json' format: data must be a dictionary, which will be appended to the existing JSON array
            - For 'jsonl' format: data must be a dictionary, which will be appended as a new line
            Defaults to False.

    Raises:
        ValueError: If data is not in the correct format for the specified file format,
                    or if an invalid format is specified.
        TypeError: If data is not JSON-serializable.
        IOError: If there's an error writing to the file.
    """

Examples

Example 1: Loading a JSON array of objects

data.json:

[
  {"name": "Alice", "age": 30},
  {"name": "Bob", "age": 25}
]

Python code:

from jload import jload

data = jload('data.json')
print(data)
# Output: [{'name': 'Alice', 'age': 30}, {'name': 'Bob', 'age': 25}]

Example 2: Loading a single JSON object

data.json:

{"name": "Alice", "age": 30}

Python code:

from jload import jload

data = jload('data.json')
print(data)
# Output: [{'name': 'Alice', 'age': 30}]

Example 3: Loading a JSONL file

data.jsonl:

{"name": "Alice", "age": 30}
{"name": "Bob", "age": 25}

Python code:

from jload import jload

data = jload('data.jsonl')
print(data)
# Output: [{'name': 'Alice', 'age': 30}, {'name': 'Bob', 'age': 25}]

Example 4: Saving data as JSON

from jload import jsave

data = [{'name': 'Alice', 'age': 30}, {'name': 'Bob', 'age': 25}]
jsave(data, 'output.json')

output.json:

[
  {
    "name": "Alice",
    "age": 30
  },
  {
    "name": "Bob",
    "age": 25
  }
]

Example 5: Saving data as JSONL

from jload import jsave

data = [{'name': 'Alice', 'age': 30}, {'name': 'Bob', 'age': 25}]
jsave(data, 'output.jsonl')

output.jsonl:

{"name":"Alice","age":30}
{"name":"Bob","age":25}

Example 6: Appending data to existing files

from jload import jsave, jsave_append

# First, create the initial files
initial_data = [{'name': 'Alice', 'age': 30}]
jsave(initial_data, 'people.json')  # Creates a JSON array file
jsave(initial_data, 'people.jsonl')  # Creates a JSONL file

# Now append a new entry to both files
new_entry = {'name': 'Bob', 'age': 25}

# Method 1: Using jsave with append=True
jsave(new_entry, 'people.json', append=True)
jsave(new_entry, 'people.jsonl', append=True)

# Method 2: Using jsave_append directly
another_entry = {'name': 'Charlie', 'age': 35}
jsave_append(another_entry, 'people.json')
jsave_append(another_entry, 'people.jsonl')

# Result for people.json:
# [
#   {"name": "Alice", "age": 30},
#   {"name": "Bob", "age": 25},
#   {"name": "Charlie", "age": 35}
# ]

# Result for people.jsonl:
# {"name":"Alice","age":30}
# {"name":"Bob","age":25}
# {"name":"Charlie","age":35}

Requirements

  • Python 3.7+

License

MIT License

Contributing

Issues and pull requests are welcome at https://github.com/Imbernoulli/jload/issues

Metadata

Release files for jload 0.7.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for jload 0.7.1
File Size Uploaded Provenance Actions
jload-0.7.1.tar.gz 10.4 kB Without provenance Details for jload-0.7.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for jload 0.7.1
File Interpreter ABI Platform Actions
jload-0.7.1-py3-none-any.whl Python 3 none any Details for jload-0.7.1-py3-none-any.whl

Total release size: 20.4 kB

Release files / jload-0.7.1.tar.gz

Download URL jload-0.7.1.tar.gz
Size 10.4 kB
Tags Source
SHA-256 checksum
How to use checksums
a92bb6494f5c825da996db5ea5819884d98a462e2a93d9281f9f579a31d889ef
BLAKE2b-256 checksum
How to use checksums
948f10c1f393f57fc086331fa476ee1c279a919e3c4b81daa951012e0e504920
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.2

Release files / jload-0.7.1-py3-none-any.whl

Download URL jload-0.7.1-py3-none-any.whl
Size 9.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
85a527e2e769b031899300e0fc43750dfe72a36ed38412f6fb8c77cf139b42ea
BLAKE2b-256 checksum
How to use checksums
57110beee02bd51ddf4cc374124b87d0d92fa7fe142cdb8fc9d220c20f0ff5b1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.2

Security for jload 0.7.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page