Python: json.loads подавляется выходами - PullRequest
18 голосов
/ 01 октября 2009

У меня есть приложение, которое отправляет объект JSON (отформатированный с помощью Prototype) на сервер ASP. На сервере модуль json Python 2.6 пытается загрузить () JSON, но он задыхается от некоторой комбинации обратных слешей. Обратите внимание:

>>> s
'{"FileExists": true, "Version": "4.3.2.1", "Path": "\\\\host\\dir\\file.exe"}'

>>> tmp = json.loads(s)
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
  {... blah blah blah...}
  File "C:\Python26\lib\json\decoder.py", line 155, in JSONString
    return scanstring(match.string, match.end(), encoding, strict)
  ValueError: Invalid \escape: line 1 column 58 (char 58)

>>> s[55:60]
u'ost\\d'

Таким образом, столбец 58 - это экранированный обратный слеш. Я думал, что это правильно сбежал! UNC \\host\dir\file.exe, так что я только удвоил слэш. Но, видимо, это не хорошо. Может ли кто-нибудь помочь? В крайнем случае я рассматриваю преобразование \ в /, а затем обратно, но мне это кажется настоящим хаком.

Заранее спасибо!

Ответы [ 3 ]

22 голосов
/ 01 октября 2009

Правильный JSON:

r'{"FileExists": true, "Version": "4.3.2.1", "Path": "\\\\host\\dir\\file.exe"}'

Обратите внимание на букву r, если вы ее опустите, вам нужно экранировать \ и для Python.

>>> import json
>>> d = json.loads(s)
>>> d.keys()
[u'FileExists', u'Path', u'Version']
>>> d.values()
[True, u'\\\\host\\dir\\file.exe', u'4.3.2.1']

Обратите внимание на разницу:

>>> repr(d[u'Path'])
"u'\\\\\\\\host\\\\dir\\\\file.exe'"
>>> str(d[u'Path'])
'\\\\host\\dir\\file.exe'
>>> print d[u'Path']
\\host\dir\file.exe

Python REPL по умолчанию печатает repr(obj) для объекта obj:

>>> class A:
...   __str__ = lambda self: "str"
...   __repr__  = lambda self: "repr"
... 
>>> A()
repr
>>> print A()
str

Поэтому ваша исходная строка s неправильно экранирована для JSON. Он содержит неоткрытые '\d' и '\f'. print s должен показывать '\\d', иначе это не правильный JSON.

ПРИМЕЧАНИЕ. Строка JSON - это набор из нуля или более символов Юникода, заключенный в двойные кавычки с использованием обратной косой черты ( json.org ). Я пропустил проблемы кодирования (а именно, преобразование байтовых строк в юникод и наоборот) в приведенных выше примерах.

5 голосов
/ 14 июня 2016

Поскольку исключение дает вам индекс сбойного escape-символа, этот небольшой хак, который я разработал, может быть хорош:)

def fix_JSON(json_message=None):
    result = None
    try:        
        result = json.loads(json_message)
    except Exception as e:      
        # Find the offending character index:
        idx_to_replace = int(e.message.split(' ')[-1].replace(')',''))      
        # Remove the offending character:
        json_message = list(json_message)
        json_message[idx_to_replace] = ' '
        new_message = ''.join(json_message)     
        return fix_JSON(json_message=new_message)
    return result
1 голос
/ 01 октября 2009
>>> s
'{"FileExists": true, "Version": "4.3.2.1", "Path": "\\\\host\\dir\\file.exe"}'
>>> print s
{"FileExists": true, "Version": "4.3.2.1", "Path": "\\host\dir\file.exe"}

Вы на самом деле не экранировали строку, поэтому она пытается проанализировать недопустимые escape-коды, такие как \d или \f. Попробуйте использовать хорошо протестированный кодер JSON, например json2.js .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...