如何从带有未转义反斜杠的JSON文件中读取?

时间:2017-02-13 15:00:27

标签: python json python-2.7 escaping

我有一个包含连接字符串的JSON文件:

abc.json

{
  "host":"1.2.3.4",
  "user":"abc",
  "passwd":"s&]\yz$&u42/",
  "dbname":"sample",
  "port":2341
}

这是我的Python脚本,它试图读取数据:

 import psycopg2 as pg
 dbconn = "C:\abc.json"
 with open(dbconn) as conn_file:
     conn = json.load(conn_file)

它给了我这个错误:

json.decoder.JSONDecodeError: Invalid \escape: line 4 column 16 (char 53)

如何解决此错误?

2 个答案:

答案 0 :(得分:3)

您的文件无效:JSON中没有\y这样的转义序列,裸露的反斜杠本身必须进行转义:\\

如果可以,最简单的解决方案是通过转义反斜杠来修复您的文件,使其成为有效的JSON。

如果由于某种原因你无法为json.loads()编写一个包装器来捕获此特定错误并修补源文本:

import json
from json.decoder import JSONDecodeError

def permissive_json_loads(text):
    while True:
        try:
            data = json.loads(text)
        except JSONDecodeError as exc:
            if exc.msg == 'Invalid \\escape':
                text = text[:exc.pos] + '\\' + text[exc.pos:]
            else:
                raise
        else:
            return data

为简单起见,上面的函数采用字符串而不是文件。

它也是一种破坏坚果的大锤。方法,反复尝试加载整个JSON文档并在找到它们时修复任何未转义的反斜杠 - 这对于很少出现问题的小型JSON文档是合理的,但如果您正在处理包含大量这些文档的大型JSON文档则不太合适未转义的反斜杠错误。

这是在行动:

>>> print(text)
{
  "host":"1.2.3.4",
  "user":"abc",
  "passwd":"s&]\yz$&u42/",
  "dbname":"sample",
  "port":2341
}

>>> config = permissive_json_loads(text)
>>> print(config['passwd'])
s&]\yz$&u42/

在您的情况下,您要从文件中读取字符串,然后调用该函数:

 dbconn = "C:\abc.json"
 with open(dbconn) as conn_file:
     conn_doc = conn_file.read()
 conn = permissive_json_loads(conn_doc)

答案 1 :(得分:0)

Python> = 2.7.15似乎产生与Python3相同的错误消息:

test = """
{
  "host":"1.2.3.4",
  "user":"abc",
  "passwd":"s&]\yz$&u42/",
  "dbname":"sample",
  "port":2341
}
"""

print json.loads(test)

错误:

  

ValueError:无效\ escape:第5行第16列(字符54)

稍微修改@Zero Piraeus's代码使其可以在Python2.7下工作:

import json
import re

def permissive_json_loads(text):
    _rePattern = re.compile(r'''(\d+)\)$''', re.MULTILINE)

    i = 0
    #  Make sure the loop is going to terminate.
    #  There wont be more iterations than the double amout of characters
    while True:
        i += 1
        if i > len(text) * 2:
            return
        try:
            data = json.loads(text)
        except ValueError, exc:
            exMsg = str(exc)
            if exMsg.startswith('Invalid \\escape'):
                m = re.search(_rePattern, exMsg)
                if not m:
                    return

                pos = int(m.groups()[0])
                print "Replacing at: %d" % pos
                text = text[:pos] + '\\' + text[pos:]
            else:
                raise
        else:
            return data

text = """
{
  "host":"1.2.3.4",
  "user":"abc",
  "passwd":"s&]\yz$&u42/",
  "dbname":"sample",
  "port":2341
}
"""

i = permissive_json_loads(text)
print i

打印:

Replacing at position: 54
{u'passwd': u's&]\\yz$&u42/', u'host': u'1.2.3.4', u'port': 2341, u'user': u'abc', u'dbname': u'sample'}