json-repair


Namejson-repair JSON
Version 0.16.1 PyPI version JSON
download
home_pageNone
SummaryA package to repair broken json strings
upload_time2024-04-30 06:18:27
maintainerNone
docs_urlNone
authorNone
requires_python>=3.7
licenseMIT License Copyright (c) 2023 Stefano Baccianella Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
keywords json repair llm parser
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            This simple package can be used to fix an invalid json string. To know all cases in which this package will work, check out the unit test.

Inspired by https://github.com/josdejong/jsonrepair

# Motivation
Some LLMs are a bit iffy when it comes to returning well formed JSON data, sometimes they skip a parentheses and sometimes they add some words in it, because that's what an LLM does.
Luckily, the mistakes LLMs make are simple enough to be fixed without destroying the content.

I searched for a lightweight python package that was able to reliably fix this problem but couldn't find any.

*So I wrote one*

# How to use
    from json_repair import repair_json

    good_json_string = repair_json(bad_json_string)
    # If the string was super broken this will return an empty string

You can use this library to completely replace `json.loads()`:

    import json_repair

    decoded_object = json_repair.loads(json_string)

or just

    import json_repair

    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:

    from json_repair import repair_json

    good_json_string = repair_json(bad_json_string, skip_json_loads=True)

I made a choice of not using any fast json library to avoid having any external dependency, so that anybody can use it regardless of their stack.

Some rules of thumb to use:
- Setting `return_objects=True` will always be faster because the parser returns an object already and it doesn't have serialize that object to JSON
- `skip_json_loads` is faster only if you 100% know that the string is not a valid JSON
- If you are having issues with escaping pass the string as **raw** string like: `r"string with escaping\""`
## Adding to requirements
**Please pin this library only on the major version!**

We use TDD and strict semantic versioning, there will be frequent updates and no breaking changes in minor and patch versions.
To ensure that you only pin the major version of this library in your `requirements.txt`, specify the package name followed by the major version and a wildcard for minor and patch versions. For example:

    json_repair==0.*

In this example, any version that starts with `0.` will be acceptable, allowing for updates on minor and patch versions.

# How it works
This module will parse the JSON file following the BNF definition:

    <json> ::= <primitive> | <container>

    <primitive> ::= <number> | <string> | <boolean>
    ; Where:
    ; <number> is a valid real number expressed in one of a number of given formats
    ; <string> is a string of valid characters enclosed in quotes
    ; <boolean> is one of the literal strings 'true', 'false', or 'null' (unquoted)

    <container> ::= <object> | <array>
    <array> ::= '[' [ <json> *(', ' <json>) ] ']' ; A sequence of JSON values separated by commas
    <object> ::= '{' [ <member> *(', ' <member>) ] '}' ; A sequence of 'members'
    <member> ::= <string> ': ' <json> ; A pair consisting of a name, and a JSON value

If something is wrong (a missing parantheses or quotes for example) it will use a few simple heuristics to fix the JSON string:
- Add the missing parentheses if the parser believes that the array or object should be closed
- Quote strings or add missing single quotes
- Adjust whitespaces and remove line breaks

I am sure some corner cases will be missing, if you have examples please open an issue or even better push a PR

# How to develop
Just create a virtual environment with `requirements.txt`, the setup uses [pre-commit](https://pre-commit.com/) to make sure all tests are run.

Make sure that the Github Actions running after pushing a new commit don't fail as well.

# How to release
You will need owner access to this repository
- Edit `pyproject.toml` and update the version number appropriately using `semver` notation
- **Commit and push all changes to the repository before continuing or the next steps will fail**
- Run `python -m build`
- Create a new release in Github, making sure to tag all the issues solved and contributors. Create the new tag, same as the one in the build configuration
- Once the release is created, a new Github Actions workflow will start to publish on Pypi, make sure it didn't fail
---
# Repair JSON in other programming languages
- Typescript: https://github.com/josdejong/jsonrepair
- Go: https://github.com/RealAlexandreAI/json-repair
---
# Bonus Content
If you need some good Custom Instructions (System Message) to improve your chatbot responses try https://gist.github.com/mangiucugna/7ec015c4266df11be8aa510be0110fe4

---
## Star History

[![Star History Chart](https://api.star-history.com/svg?repos=mangiucugna/json_repair&type=Date)](https://star-history.com/#mangiucugna/json_repair&Date)

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "json-repair",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.7",
    "maintainer_email": null,
    "keywords": "JSON, REPAIR, LLM, PARSER",
    "author": null,
    "author_email": "Stefano Baccianella <4247706+mangiucugna@users.noreply.github.com>",
    "download_url": "https://files.pythonhosted.org/packages/42/e1/05ef8fbab36f753579bd8f0e9eb34d122abd45aa4516ab1c8f66854ec654/json_repair-0.16.1.tar.gz",
    "platform": null,
    "description": "This simple package can be used to fix an invalid json string. To know all cases in which this package will work, check out the unit test.\n\nInspired by https://github.com/josdejong/jsonrepair\n\n# Motivation\nSome LLMs are a bit iffy when it comes to returning well formed JSON data, sometimes they skip a parentheses and sometimes they add some words in it, because that's what an LLM does.\nLuckily, the mistakes LLMs make are simple enough to be fixed without destroying the content.\n\nI searched for a lightweight python package that was able to reliably fix this problem but couldn't find any.\n\n*So I wrote one*\n\n# How to use\n    from json_repair import repair_json\n\n    good_json_string = repair_json(bad_json_string)\n    # If the string was super broken this will return an empty string\n\nYou can use this library to completely replace `json.loads()`:\n\n    import json_repair\n\n    decoded_object = json_repair.loads(json_string)\n\nor just\n\n    import json_repair\n\n    decoded_object = json_repair.repair_json(json_string, return_objects=True)\n\n### Read json from a file or file descriptor\n\nJSON repair provides also a drop-in replacement for `json.load()`:\n\n    import json_repair\n\n    try:\n        file_descriptor = open(fname, 'rb')\n    except OSError:\n        ...\n\n    with file_descriptor:\n        decoded_object = json_repair.load(file_descriptor)\n\nand another method to read from a file:\n\n    import json_repair\n\n    try:\n        decoded_object = json_repair.from_file(json_file)\n    except OSError:\n        ...\n    except IOError:\n        ...\n\nKeep in mind that the library will not catch any IO-related exception and those will need to be managed by you\n\n### Performance considerations\nIf 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:\n\n    from json_repair import repair_json\n\n    good_json_string = repair_json(bad_json_string, skip_json_loads=True)\n\nI made a choice of not using any fast json library to avoid having any external dependency, so that anybody can use it regardless of their stack.\n\nSome rules of thumb to use:\n- Setting `return_objects=True` will always be faster because the parser returns an object already and it doesn't have serialize that object to JSON\n- `skip_json_loads` is faster only if you 100% know that the string is not a valid JSON\n- If you are having issues with escaping pass the string as **raw** string like: `r\"string with escaping\\\"\"`\n## Adding to requirements\n**Please pin this library only on the major version!**\n\nWe use TDD and strict semantic versioning, there will be frequent updates and no breaking changes in minor and patch versions.\nTo ensure that you only pin the major version of this library in your `requirements.txt`, specify the package name followed by the major version and a wildcard for minor and patch versions. For example:\n\n    json_repair==0.*\n\nIn this example, any version that starts with `0.` will be acceptable, allowing for updates on minor and patch versions.\n\n# How it works\nThis module will parse the JSON file following the BNF definition:\n\n    <json> ::= <primitive> | <container>\n\n    <primitive> ::= <number> | <string> | <boolean>\n    ; Where:\n    ; <number> is a valid real number expressed in one of a number of given formats\n    ; <string> is a string of valid characters enclosed in quotes\n    ; <boolean> is one of the literal strings 'true', 'false', or 'null' (unquoted)\n\n    <container> ::= <object> | <array>\n    <array> ::= '[' [ <json> *(', ' <json>) ] ']' ; A sequence of JSON values separated by commas\n    <object> ::= '{' [ <member> *(', ' <member>) ] '}' ; A sequence of 'members'\n    <member> ::= <string> ': ' <json> ; A pair consisting of a name, and a JSON value\n\nIf something is wrong (a missing parantheses or quotes for example) it will use a few simple heuristics to fix the JSON string:\n- Add the missing parentheses if the parser believes that the array or object should be closed\n- Quote strings or add missing single quotes\n- Adjust whitespaces and remove line breaks\n\nI am sure some corner cases will be missing, if you have examples please open an issue or even better push a PR\n\n# How to develop\nJust create a virtual environment with `requirements.txt`, the setup uses [pre-commit](https://pre-commit.com/) to make sure all tests are run.\n\nMake sure that the Github Actions running after pushing a new commit don't fail as well.\n\n# How to release\nYou will need owner access to this repository\n- Edit `pyproject.toml` and update the version number appropriately using `semver` notation\n- **Commit and push all changes to the repository before continuing or the next steps will fail**\n- Run `python -m build`\n- Create a new release in Github, making sure to tag all the issues solved and contributors. Create the new tag, same as the one in the build configuration\n- Once the release is created, a new Github Actions workflow will start to publish on Pypi, make sure it didn't fail\n---\n# Repair JSON in other programming languages\n- Typescript: https://github.com/josdejong/jsonrepair\n- Go: https://github.com/RealAlexandreAI/json-repair\n---\n# Bonus Content\nIf you need some good Custom Instructions (System Message) to improve your chatbot responses try https://gist.github.com/mangiucugna/7ec015c4266df11be8aa510be0110fe4\n\n---\n## Star History\n\n[![Star History Chart](https://api.star-history.com/svg?repos=mangiucugna/json_repair&type=Date)](https://star-history.com/#mangiucugna/json_repair&Date)\n",
    "bugtrack_url": null,
    "license": "MIT License  Copyright (c) 2023 Stefano Baccianella  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ",
    "summary": "A package to repair broken json strings",
    "version": "0.16.1",
    "project_urls": {
        "Bug Tracker": "https://github.com/mangiucugna/json_repair/issues",
        "Homepage": "https://github.com/mangiucugna/json_repair/"
    },
    "split_keywords": [
        "json",
        " repair",
        " llm",
        " parser"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "40b48f8ed02d90abc9bb61eed56220cfe79f0e15d412c7e9ff50ec0e3737b62c",
                "md5": "fc38f3f1e9b9c42af209ff196814cfeb",
                "sha256": "c84f00a030ca968e88fd0539ef1ff02ca1d9774d12fc671af05138970d48d98c"
            },
            "downloads": -1,
            "filename": "json_repair-0.16.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "fc38f3f1e9b9c42af209ff196814cfeb",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7",
            "size": 10828,
            "upload_time": "2024-04-30T06:18:26",
            "upload_time_iso_8601": "2024-04-30T06:18:26.057976Z",
            "url": "https://files.pythonhosted.org/packages/40/b4/8f8ed02d90abc9bb61eed56220cfe79f0e15d412c7e9ff50ec0e3737b62c/json_repair-0.16.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "42e105ef8fbab36f753579bd8f0e9eb34d122abd45aa4516ab1c8f66854ec654",
                "md5": "0eeade7751039d2d225dbb0a1a095084",
                "sha256": "12c21f607f66516bfd8ef6f509fa9d757924ff9ad83347d2449f7881b8ecf6f7"
            },
            "downloads": -1,
            "filename": "json_repair-0.16.1.tar.gz",
            "has_sig": false,
            "md5_digest": "0eeade7751039d2d225dbb0a1a095084",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7",
            "size": 17688,
            "upload_time": "2024-04-30T06:18:27",
            "upload_time_iso_8601": "2024-04-30T06:18:27.621247Z",
            "url": "https://files.pythonhosted.org/packages/42/e1/05ef8fbab36f753579bd8f0e9eb34d122abd45aa4516ab1c8f66854ec654/json_repair-0.16.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-04-30 06:18:27",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "mangiucugna",
    "github_project": "json_repair",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [],
    "lcname": "json-repair"
}
        
Elapsed time: 0.24999s