2009-10-01 5 views
11

Mam aplikację, która wysyła obiekt JSON (sformatowany za pomocą prototypu) do serwera ASP. Na serwerze moduł Python 2.6 "json" próbuje załadować() JSON, ale dusi się na niektórych kombinacjach ukośników odwrotnych. Obserwuj:Python: json.loads dławiki po ucieczkach

>>> 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' 

Tak więc kolumna 58 jest ukośnikiem odwrotnym. Myślałem, że to właściwie uciekło! UNC to \\host\dir\file.exe, więc podwoiłem się na ukośnikach. Ale najwyraźniej nie jest to dobre. Czy ktoś może pomóc? W ostateczności rozważam konwersję \ do/i znowu z powrotem, ale wydaje mi się, że to prawdziwy hack do mnie.

Z góry dziękuję!

Odpowiedz

16

Prawidłowe json jest:

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

Uwaga list r jeśli pominąć to trzeba uciec \ dla Python też.

>>> 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'] 

zauważyć różnicę:

>>> 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 

drukuje Python rEPL domyślnie repr(obj) dla obiektu obj:

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

Dlatego oryginalny s ciąg nie jest właściwie uciekł do JSON. Zawiera nieodwracane linie: '\d' i '\f'. print s musi pokazać '\\d' w przeciwnym razie nie jest prawidłowy JSON.

UWAGA: Ciąg JSON to zbiór zero lub więcej znaków Unicode, zawijany w podwójne cudzysłowy, z użyciem odwrotnych ukośników (json.org). W powyższych przykładach pominąłem problemy z kodowaniem (a mianowicie transformacja z ciągów bajtowych do Unicode i na odwrót).

+0

:) >>> s = r '{ "FileExists": true , "Wersja": "4.3.2.1", "Ścieżka": "\\\\ host \\ dir \\ plik.exe"} ' >>> json.loads (s) {u'FileExists " : True, u'Path ': u' \\\\ host \\ dir \\ file.exe ', u'Version': u'4.3.2.1 '} – Chris

+0

Co tak naprawdę r robi? Jak mogę zastosować go do łańcucha, który jest już przechowywany jako, powiedzmy, "foo". Czy to jakieś kodowanie? – Chris

+0

'' s = ''łamie formatowanie. – jfs

1
>>> 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"} 

nie zostały faktycznie uciekł ciąg, więc próbuje analizować nieprawidłowe kody ucieczki jak \d lub \f. Rozważ użycie dobrze przetestowanego kodera JSON, takiego jak json2.js.

2

Ponieważ wyjątek daje indeks znaku wykraczająca ucieczki, ten mały kilof opracowałem może być ładne :)

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

Dzięki za kod. W moim przypadku (Python 3.5) potrzebowałem zmienić 'idx_to_replace = int (e.message.split ('') [- 1] .replace (')', ''))) na' idx_to_replace = int (str (e) .split ('') [- 1] .replace (')', '')) ' – TitanFighter

Powiązane problemy