Python中使用嵌套引号解析类JSON字符串

nlejzf6q  于 2023-10-21  发布在  Python
关注(0)|答案(1)|浏览(157)

我试图在Python中解析一个类似JSON的字符串,但我遇到了嵌套引号的问题。具体来说,字符串在引号中包含引号,这会导致JSON解析器失败。下面是一个有问题的字符串的例子:

{
  "text": "This is a "test" string",
  "another_key": "Another value"
}

正如您所看到的,键“text”的值在单词“test”周围包含了额外的引号,这就是导致问题的原因。
我尝试了各种方法来清理字符串并将其转换为Python字典,但到目前为止还没有一种有效的方法。下面是我尝试的一个示例函数:

def clean_and_convert_to_dict(input_str):
    new_str = ''
    in_string = False
    for char in input_str:
        if char == '"':
            in_string = not in_string

        if in_string:
            if char == '"':
                new_str += '\\"'
            elif char == '\n':
                new_str += '\\n'
            else:
                new_str += char
        else:
            if char != '\n':
                new_str += char
    try:
        return json.loads(new_str), "Conversion successful."
    except json.JSONDecodeError as e:
        return None, f"Conversion error: {e}"

此函数尝试转义嵌套的引号,但它没有按预期工作。我正在寻找一个函数,可以正确处理这些嵌套的引号,并将字符串转换为Python字典。
任何帮助将不胜感激!
我尝试编写一个Python函数,通过转义嵌套的引号来清理字符串,以便可以使用json.loads()将其成功转换为Python字典。我希望函数返回一个字典。
该功能未按预期工作。它没有成功地将字符串转换为字典,而是抛出了一个json. JSONDecodeError。字符串中嵌套的引号似乎是问题的根源,我的函数没有正确处理它们。

d6kp6zgx

d6kp6zgx1#

正如其他人评论的那样,如果没有一个规范,解析某个东西可能会很困难。但是......有时候生活会给你柠檬,而你的工作就是做柠檬水。
有人已经为JSON编写了一个解码器,当它出现问题时,产生的异常有一个.pos属性,它告诉你解码器到底在哪里混淆了。这至少适用于您所述的案例:

import json

def fix_embedded_quotes(input_str):
    if input_str.count('"') % 2 != 0:
        raise ValueError("unbalanced quotes -- can't deal")

    while True:
        try:
            return json.loads(input_str)
        except json.decoder.JSONDecodeError as exc:
            # if the problem is at quote, we can try to fix it.  Otherwise, we
            # have bigger issues
            if input_str[exc.pos - 1] != '"':
                raise

            # escape our problem child
            input_str = (
                input_str[: exc.pos - 1] + '\\' + input_str[exc.pos - 1 :]
            )

            # escape the next quote
            next_quote = input_str.find('"', exc.pos + 1)
            input_str = (
                input_str[:next_quote] + '\\' + input_str[next_quote:]
            )

import unittest

class MyTest(unittest.TestCase):
    def test_valid_json(self):
        """first, do no harm"""
        result = fix_embedded_quotes(
            '{"foo" : "bar", "baz" : ["a", "b", "c"]}'
        )
        assert result['foo'] == 'bar'
        assert len(result['baz']) == 3

    def test_invalid_json(self):
        """ensure we deal with non-quote-related errors"""
        with self.assertRaises(json.decoder.JSONDecodeError):
            fix_embedded_quotes('{"foo" : "bar", "baz" : ["a", "b", "c"]')

    def test_original_case(self):
        result = fix_embedded_quotes(
            '{"text": "This is a "test" string","another_key": "Another value"}'
        )

        assert result['text'] == "This is a \"test\" string"
        assert result['another_key'] == "Another value"

    def test_quote_in_list(self):
        result = fix_embedded_quotes(
            '''["This is a "test" string",
                "Another value"
                ]
            '''
        )
        assert result[0] == "This is a \"test\" string"
        assert result[1] == "Another value"

if __name__ == "__main__":
    unittest.main()

相关问题