Skip to content

Commit

Permalink
Fix #21
Browse files Browse the repository at this point in the history
- Added a drop-in replacement for `json.load()`
- Added a new function `from_file` that is essentially syntactic sugar on top of load and take a file path as string and returns an object like `json.load()`
  • Loading branch information
mangiucugna committed Apr 11, 2024
1 parent cf9f5c0 commit 7d91782
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 5 deletions.
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,33 @@ or just

decoded_object = json_repair.repair_json(json_string, return_objects=True)

### Read json from a file or file descriptor

JSON repair provides also a drop-in replacement for `json.load()`:

import json_repair

try:
file_descriptor = open(fname, 'rb')
except OSError:
...

with file_descriptor:
decoded_object = json_repair.load(file_descriptor)

and another method to read from a file:

import json_repair

try:
decoded_object = json_repair.from_file(json_file)
except OSError:
...
except IOError:
...

Keep in mind that the library will not catch any IO-related exception and those will need to be managed by you

### Performance considerations
If you find this library too slow because is using `json.loads()` you can skip that by passing `skip_json_loads=True` to `repair_json`. Like:

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"
[project]
name = "json_repair"
version = "0.12.3"
version = "0.13.0"
license = {file = "LICENSE"}
authors = [
{ name="Stefano Baccianella", email="[email protected]" },
Expand Down
2 changes: 2 additions & 0 deletions src/json_repair/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
from .json_repair import repair_json as repair_json
from .json_repair import loads as loads
from .json_repair import loads as load
from .json_repair import loads as from_file
16 changes: 15 additions & 1 deletion src/json_repair/json_repair.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"""

import json
from typing import Any, Dict, List, Union
from typing import Any, Dict, List, Union, TextIO


class JSONParser:
Expand Down Expand Up @@ -351,3 +351,17 @@ def loads(
It is a wrapper around the `repair_json()` function with `return_objects=True`.
"""
return repair_json(json_str, True)


def load(fp: TextIO) -> Union[Dict[str, Any], List[Any], str, float, int, bool, None]:
return loads(fp.read())


def from_file(
filename: str,
) -> Union[Dict[str, Any], List[Any], str, float, int, bool, None]:
fd = open(filename)
jsonobj = load(fd)
fd.close()

return jsonobj
21 changes: 19 additions & 2 deletions tests/test_json_repair.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from src.json_repair.json_repair import repair_json
from src.json_repair.json_repair import from_file, repair_json


def test_repair_json():
Expand Down Expand Up @@ -240,4 +240,21 @@ def test_repair_json_skip_json_loads():
assert repair_json('{"key": true, "key2": false, "key3": null}', skip_json_loads=True) == '{"key": true, "key2": false, "key3": null}'
assert repair_json('{"key": true, "key2": false, "key3": null}', return_objects=True, skip_json_loads=True) == {"key": True, "key2": False, "key3": None}
assert repair_json('{"key": true, "key2": false, "key3": }', skip_json_loads=True) == '{"key": true, "key2": false, "key3": ""}'
assert repair_json('{"key": true, "key2": false, "key3": }', return_objects=True, skip_json_loads=True) == {"key": True, "key2": False, "key3": ""}
assert repair_json('{"key": true, "key2": false, "key3": }', return_objects=True, skip_json_loads=True) == {"key": True, "key2": False, "key3": ""}

def test_repair_json_from_file():
import os
import tempfile

# Create a temporary file
temp_fd, temp_path = tempfile.mkstemp(suffix=".json")
try:
# Write content to the temporary file
with os.fdopen(temp_fd, 'w') as tmp:
tmp.write("{")

assert(from_file(temp_path)) == {}

finally:
# Clean up - delete the temporary file
os.remove(temp_path)
2 changes: 1 addition & 1 deletion tests/test_performance.py
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ def test_true_false_correct(benchmark):
mean_time = benchmark.stats.get("median")

# Define your time threshold in seconds
max_time = 23 * (1 / 10 ** 6) # 23 microsecond
max_time = 24 * (1 / 10 ** 6) # 24 microsecond

# Assert that the average time is below the threshold
assert mean_time < max_time, f"Benchmark exceeded threshold: {mean_time:.3f}s > {max_time:.3f}s"
Expand Down

0 comments on commit 7d91782

Please sign in to comment.