2016-06-07 3 views
0

Я читаю файл JSON в Python, который содержит скрытые одинарные кавычки (\ '). Это приводит ко всем видам икоты, как хорошо обсуждается, например. here. Тем не менее, я не мог найти ничего о том, как адрес вопрос. Я только что сделалРабота с неправильно экранированными символами в JSON

newstring=originalstring.replace(r"\'", "'") 

и все получилось. Но это кажется довольно уродливым. Я не мог найти много материала о том, как справиться с подобным делом (создавая исключение или что-то еще) в json docs.

  • Есть ли хорошая, чистая процедура для такой проблемы?

Возвращение к источнику невозможно, к сожалению.

Благодарим за помощь!

+1

Параметр '\ '' последовательность символов действительно недействителен JSON, потому что нет такой последовательности бежать в формате JSON. Как вы производили этот вывод в первую очередь? –

+0

Привет, Martijn, я не производил его вообще, просто работая с тем, что было дано мне. По-видимому, он был создан с помощью «Экспорт в JSON-плагин для PHPMyAdmin». – patrick

+0

Рассмотрите возможность подачи отчета об ошибке в этот проект. –

ответ

1

JSON standard определяет конкретный набор valid 2-character escape sequences: \\, \/, \", \b, \r, \n, \f и \t, и одна последовательность символов 4 символов определить любой элемент кода Unicode, \uhhhh (\u плюс 4 гекс цифр). Любая другая последовательность обратной косой черты плюс другой символ: недействительный JSON.

Если у вас есть источник JSON вы не можете исправить иначе, единственный выход, чтобы удалить недопустимые последовательности, как вы сделали с str.replace(), даже если это немного хрупким (это будет перерыва когда есть четная обратная косая черта, предшествующая цитате).

Вы можете использовать регулярное выражение тоже, где вы удалите любые обратные слэши не используются в действительной последовательности:

fixed = re.sub(r'(?<!\\)\\(?!["\\/bfnrt]|u[0-9a-fA-F]{4})', r'', inputstring) 

Это не подловить последовательность обратной косой нечетным счета как \\\ но поймает все остальное:

>>> import re, json 
>>> broken = r'"JSON string with escaped quote: \' and various other broken escapes: \a \& \$ and a newline!\n"' 
>>> json.loads(broken) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.5/json/__init__.py", line 319, in loads 
    return _default_decoder.decode(s) 
    File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.5/json/decoder.py", line 339, in decode 
    obj, end = self.raw_decode(s, idx=_w(s, 0).end()) 
    File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.5/json/decoder.py", line 355, in raw_decode 
    obj, end = self.scan_once(s, idx) 
json.decoder.JSONDecodeError: Invalid \escape: line 1 column 34 (char 33) 
>>> json.loads(re.sub(r'(?<!\\)\\(?!["\\/bfnrt]|u[0-9a-fA-F]{4})', r'', broken)) 
"JSON string with escaped quote: ' and various other broken escapes: a & $ and a newline!\n" 
+0

Спасибо за помощь! – patrick

1

Правильная вещь - исправить все, что создает недопустимый JSON-файл. Но если это невозможно, я думаю, что замена необходима. Но вы должны использовать регулярное выражение, чтобы оно не заменяло \\'\' - в этом случае первая обратная косая черта избегает второй обратной косой черты, они не ускользают от цитаты. Отрицательный lookbehind предотвратит это.

import re 
newstring = re.sub(r"(?<!\\)\\'", "'", originalstring) 
1

Решение не плох. Это кажется уродливым, потому что проблема уродливая - у вас поврежденные данные. Это, конечно, просто, элегантно и эффективно. Он будет сбой только в том случае, если подстрока \\' (это три символа, я ничего не избегаю) присутствует где угодно, и даже тогда, только если число последовательных косой черты равно. Таким образом, ваши варианты:

  1. Просто сделайте свою текущую вещь, но сначала проверьте if r"\\'" in originalstring и сообщите об ошибке. Легко, безопасно, возможно, прекрасно.
  2. Используйте регулярное выражение с отрицательным lookbehind для (\\\\)+ или что-то в этом роде.
  3. Поймать ошибки и использовать атрибуты ошибок для принятия решения о заменяемой части строки.

Заканчивать этот фрагмент:

import json 
from json.decoder import JSONDecodeError 

s = r'"\'"' 
print(s) 
try: 
    print(json.loads(s)) 
except JSONDecodeError as e: 
    print(vars(e)) 

Выход:

"\'" 
{'msg': 'Invalid \\escape', 'colno': 2, 'doc': '"\\\'"', 'pos': 1, 'lineno': 1} 
+0

Только в Python 3 исключение имеют эти атрибуты; в Python 2 все, что вы получите, это исключение «ValueError», и вы застряли в разборе текстового сообщения для этой информации. –

+0

Вы можете использовать 'json.JSONDecodeError', кстати, вам не нужно импортировать его из' json.decoder'. –

+0

Да, Python 2 дает мне «ValueError: Invalid \ escape»: – patrick

Смежные вопросы