Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

some ideas for improvement #5

Open
tfriedel opened this issue Dec 6, 2023 · 7 comments
Open

some ideas for improvement #5

tfriedel opened this issue Dec 6, 2023 · 7 comments

Comments

@tfriedel
Copy link

tfriedel commented Dec 6, 2023

Hi,

I was dealing with having to parse json returned from ChatGPT and was looking for some kind of best effort json parser, which is how I found this.
Good work on doing this!
I noticed that the unit tests fail currently for some instances, like parsing "12." to 12. Or the test_incomplete_string fails because no exception is raised. Here I wondered why that would even be the expected behaviour? Shouldn't a string that doesn't end with a " be parsed correctly?

Dealing with incomplete json is only one of the issues, and actually not my main issue.
I found that often ChatGPT would include newlines.

For this I found you can use

json_decoder = json.JSONDecoder(strict=False)
json_decoder.decode(s)

This will preserve the newlines, which is not really legal json, but what we want.

There's also a similar project for javascript:
https://github.com/beenotung/best-effort-json-parser

And an old python based json parser, that's supposedly also able to parse somewhat illegal json:
https://pypi.org/project/demjson/

This one is outdated and doesn't work with newer python version.

There may be some ideas for features or edge cases in those projects to help you improve this library!
Would be nice to have a very robust parser for gpt produced json.

@iw4p
Copy link
Owner

iw4p commented Dec 6, 2023

Hi
Sure! Thank you. If you want to contribute, feel free.

@korabs-x
Copy link

korabs-x commented Apr 4, 2024

@tfriedel had the same issues of newlines not being parsed correctly, found this one instead which works for us:
https://github.com/promplate/partial-json-parser

@iw4p
Copy link
Owner

iw4p commented Apr 4, 2024

@korabs-x Can you give me more details to fix it for the next version?

@korabs-x
Copy link

korabs-x commented Apr 4, 2024

Sure!
The inconsistency here should make it most clear:

>>> parser.parse('{"x": "1st line\\n2nd line').get('x')
'1st line\\n2nd line'
>>> parser.parse('{"x": "1st line\\n2nd line"').get('x')
'1st line\n2nd line'

In both versions, the \n should not be escaped. Right now it is escaped as long as the string is not finished, and switches to being not escaped once there's the finishing quotes.
Hope it helps, thanks for the otherwise great library!

@iw4p
Copy link
Owner

iw4p commented Apr 4, 2024

Oh I see! a little bit tricky to handle and fix it, but I'll try to do my best. ty!

@pthimon
Copy link

pthimon commented Apr 10, 2024

If it helps, this is how I worked around the issues of the LLM output containing real line breaks (using strict=False) and for the partial string case not handling escaped line breaks (by passing it though json.loads).

class LenientJSONParser(JSONParser):
    def parse_string(self, s, e):
        end = s.find('"', 1)
        while end != -1 and s[end - 1] == '\\':  # Handle escaped quotes
            end = s.find('"', end + 1)
        if end == -1:
            # add the missing ending quote, and parse as a json string so that escaping is handled correctly
            return json.loads(s + '"', strict=False), ""
        str_val = s[:end + 1]
        s = s[end + 1:]
        # ignore that actual newline characters might appear in the string using strict=False
        return json.loads(str_val, strict=False), s

@iw4p
Copy link
Owner

iw4p commented Aug 3, 2024

Hi everyone @pthimon @tfriedel @korabs-x
Strict mode is added. You can make it false to keep the \n characters.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants