loads - python json get value
Python: json.loads se ahoga en los escapes (3)
Tengo una aplicación que está enviando un objeto JSON (formateado con Prototype) a un servidor ASP. En el servidor, el módulo Python 2.6 "json" intenta cargar () el JSON, pero se está asfixiando con alguna combinación de barras invertidas. Observar:
>>> 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''
Así que la columna 58 es la barra invertida de escape. Pensé que esto se escapó correctamente! UNC es //host/dir/file.exe
, por lo que acabo de duplicar en barras diagonales. Pero al parecer esto no es bueno. ¿Alguien puede ayudar? Como último recurso, estoy considerando convertir el / a / y luego de nuevo, pero esto me parece un verdadero truco.
¡Gracias por adelantado!
El json correcto es:
r''{"FileExists": true, "Version": "4.3.2.1", "Path": "////host//dir//file.exe"}''
Tenga en cuenta la letra r
si la omite, también necesita escapar de 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'']
Note la diferencia:
>>> 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 imprime de forma predeterminada el repr(obj)
para un objeto obj
:
>>> class A:
... __str__ = lambda self: "str"
... __repr__ = lambda self: "repr"
...
>>> A()
repr
>>> print A()
str
Por lo tanto, la cadena de su s
original no se escapó correctamente para JSON. Contiene ''/d''
y ''/f''
. print s
debe mostrar ''//d''
contrario no es JSON correcto.
NOTA: la cadena JSON es una colección de cero o más caracteres Unicode, envueltos en comillas dobles, utilizando escapes de barra invertida ( json.org ). He omitido los problemas de codificación (es decir, la transformación de cadenas de bytes a Unicode y viceversa) en los ejemplos anteriores.
Ya que la excepción te da el índice del carácter de escape ofensivo, este pequeño truco que desarrollé podría ser bueno :)
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
>>> 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"}
Realmente no has escapado a la cadena, por lo que se trata de analizar códigos de escape no válidos como /d
o /f
. Considere usar un codificador JSON bien probado, como json2.js .