JSONDecodeError: valor esperado: línea 1 columna 1 (char 0)

260

Recibo un error Expecting value: line 1 column 1 (char 0)al intentar decodificar JSON.

La URL que uso para la llamada API funciona bien en el navegador, pero da este error cuando se realiza a través de una solicitud curl. El siguiente es el código que uso para la solicitud curl.

El error ocurre en return simplejson.loads(response_json)

    response_json = self.web_fetch(url)
    response_json = response_json.decode('utf-8')
    return json.loads(response_json)


def web_fetch(self, url):
        buffer = StringIO()
        curl = pycurl.Curl()
        curl.setopt(curl.URL, url)
        curl.setopt(curl.TIMEOUT, self.timeout)
        curl.setopt(curl.WRITEFUNCTION, buffer.write)
        curl.perform()
        curl.close()
        response = buffer.getvalue().strip()
        return response

Rastreo completo:

Rastrear:

File "/Users/nab/Desktop/myenv2/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
  111.                         response = callback(request, *callback_args, **callback_kwargs)
File "/Users/nab/Desktop/pricestore/pricemodels/views.py" in view_category
  620.     apicall=api.API().search_parts(category_id= str(categoryofpart.api_id), manufacturer = manufacturer, filter = filters, start=(catpage-1)*20, limit=20, sort_by='[["mpn","asc"]]')
File "/Users/nab/Desktop/pricestore/pricemodels/api.py" in search_parts
  176.         return simplejson.loads(response_json)
File "/Users/nab/Desktop/myenv2/lib/python2.7/site-packages/simplejson/__init__.py" in loads
  455.         return _default_decoder.decode(s)
File "/Users/nab/Desktop/myenv2/lib/python2.7/site-packages/simplejson/decoder.py" in decode
  374.         obj, end = self.raw_decode(s)
File "/Users/nab/Desktop/myenv2/lib/python2.7/site-packages/simplejson/decoder.py" in raw_decode
  393.         return self.scan_once(s, idx=_w(s, idx).end())

Exception Type: JSONDecodeError at /pricemodels/2/dir/
Exception Value: Expecting value: line 1 column 1 (char 0)
usuario1328021
fuente
2
Por último, pero no menos importante, ¿a qué print repr(response_json)te dice que te están pasando .loads()?
Martijn Pieters
44
Una más: ¿por qué usarlo simplejsoncuando puedes usar stdlib json(que es la misma biblioteca quesimplejson )?
Martijn Pieters
3
Esa es una cadena vacía. Tu web_fetch() llamada falló.
Martijn Pieters
1
Sí, te recomiendo que uses algo más fácil de usar que pycurl. requestsofrece una API mucho más fácil, especialmente cuando se trata de depurar lo que está sucediendo. A menos que tenga que tener específicamente una versión más nueva de la simplejsonbiblioteca, solo quédese jsony le ahorrará una dependencia para administrar.
Martijn Pieters
1
es response_jsonel valor de retorno de .json()? Entonces ya ha descodificado los datos y ya no necesita usarlos json.loads(). responselo descifró para ti.
Martijn Pieters

Respuestas:

125

Para resumir la conversación en los comentarios:

  • No es necesario usar la simplejsonbiblioteca, la misma biblioteca se incluye con Python como el jsonmódulo.

  • No es necesario decodificar una respuesta de UTF8 a unicode, el método simplejson/ json .loads()puede manejar los datos codificados de UTF8 de forma nativa.

  • pycurltiene una API muy arcaica. A menos que tenga un requisito específico para usarlo, hay mejores opciones.

requestsofrece la API más amigable, incluida la compatibilidad con JSON. Si puede, reemplace su llamada con:

import requests

return requests.get(url).json()
Martijn Pieters
fuente
93
¡Estoy usando este mismo error usando requests! El rastro parece sugerir que requestsusos complexjson, que usos simplejson. Extraño.
rayu
@Rayu: las solicitudes se usaránsimplejson si están disponibles; algunas personas quieren usar la última versión de simplejson en lugar de la que se incluye con Python stdlib.
Martijn Pieters
55
"No hay necesidad de usar la biblioteca simplejson, la misma biblioteca se incluye con Python como el módulo json" ... No estoy de acuerdo con respeto. simplejsonusa el integrado jsondebajo del capó, pero da errores más descriptivos. En este caso, usar jsonsolo le daría un genérico ValueError: No JSON object could be decoded.
BoltzmannBrain
2
¿Podría esto ser causado por un aborto o un json incompleto? Recibo esto al azar de vez en cuando, no estoy seguro de cómo reproducirlo.
Christophe Roussy
2
@ChristopheRoussy: sí, ese es más bien el punto de la pregunta (el OP recibió una respuesta vacía u'' ). Tu JSONDecodeErrorle dice que muchos datos se analizaron con éxito antes de que se produjera un error; eso puede ser porque hay datos no válidos en ese punto (documento JSON malformado o dañado) o porque los datos se truncaron.
Martijn Pieters
64

Verifique el cuerpo de datos de respuesta, si hay datos reales y si un volcado de datos parece estar bien formateado.

En la mayoría de los casos, su json.loads- JSONDecodeError: Expecting value: line 1 column 1 (char 0)de error se debe a:

  • citas no JSON conformes
  • Salida XML / HTML (es decir, una cadena que comienza con <), o
  • codificación de caracteres incompatible

En última instancia, el error le dice que en la primera posición la cadena ya no se ajusta a JSON.

Como tal, si el análisis falla a pesar de tener un cuerpo de datos que se parece a JSON a primera vista, intente reemplazar las comillas del cuerpo de datos:

import sys, json
struct = {}
try:
  try: #try parsing to dict
    dataform = str(response_json).strip("'<>() ").replace('\'', '\"')
    struct = json.loads(dataform)
  except:
    print repr(resonse_json)
    print sys.exc_info()

Nota: las comillas dentro de los datos se deben escapar correctamente

Lorenz Lo Sauer
fuente
44
En los comentarios estaba claro que el OP recibió una respuesta vacía. Desde requests.get(url).json()Just Works, el JSON tampoco está mal formado.
Martijn Pieters
JSONDecodeError: Expecting value: line 1 column 1 (char 0)ocurre específicamente cuando se pasa una cadena vacía a decodificación json
wesinat0r
JSONDecodeError: Expecting value: line 1 column 1 (char 0)también ocurre cuando la primera línea en la respuesta json no es válida. Ejemplo de respuesta al ejecutar un az clicomando es ["WARNING: The default kind for created storage account will change to 'StorageV2' from 'Storage' in the future", '{',. Esto me dio el error que me llevó aquí. El resto de la respuesta ES un objeto json válido. Solo esa primera línea rompe las cosas.
SeaDude
35

¡Con la requestslib JSONDecodeErrorpuede ocurrir cuando tiene un código de error http como 404 e intenta analizar la respuesta como JSON!

Primero debe verificar 200 (OK) o dejar que aumente en caso de error para evitar este caso. Desearía que fallara con un mensaje de error menos críptico.

NOTA : como Martijn Pieters declaró en los comentarios, los servidores pueden responder con JSON en caso de errores (depende de la implementación), por lo que verificar el Content-Typeencabezado es más confiable.

Christophe Roussy
fuente
Perdón por el comentario anterior, pero ¿podría vincular a un ejemplo? Estoy tratando de llevar mis habilidades de "realizar una acción" a "intentar realizar una acción, devolver la respuesta, reaccionar en consecuencia".
dcclassics
@dcclassics: Ejemplo: falla en el lado del servidor y el servidor responde mostrando una página de error (HTML) en lugar de responder con JSON, por lo que el código que analiza la respuesta intentará leer JSON pero fallará en las etiquetas HTML.
Christophe Roussy el
1
Los servidores pueden incluir cuerpos JSON en las respuestas de error. No son solo 200 respuestas correctas. Desea verificar el encabezado Content-Type.
Martijn Pieters
29

Creo que vale la pena mencionar que en los casos en que analiza el contenido de un archivo JSON en sí mismo, las comprobaciones de sanidad pueden ser útiles para asegurarse de que realmente está invocando json.loads()el contenido del archivo, a diferencia de la ruta del archivo de ese JSON :

json_file_path = "/path/to/example.json"

with open(json_file_path, 'r') as j:
     contents = json.loads(j.read())

Me da un poco de vergüenza admitir que esto puede suceder a veces:

contents = json.loads(json_file_path)
alex
fuente
Bueno ... a veces sucede. Gracias, por cierto.
Sachin Kumar el
Creo que en ese caso uno debería usar json.load()en su lugar.
Coddy
13

Verifique el formato de codificación de su archivo y use el formato de codificación correspondiente mientras lee el archivo. Resolverá tu problema.

with open("AB.json", encoding='utf-8', errors='ignore') as json_data:
     data = json.load(json_data, strict=False)
Ramineni Ravi Teja
fuente
3
Esto funcionó para mí con el pequeño cambio de encoding='utf-8', así que supongo que a veces necesitas probar algunas cosas.
RobertMyles
9

Muchas veces, esto se debe a que la cadena que está intentando analizar está en blanco:

>>> import json
>>> x = json.loads("")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/__init__.py", line 348, in loads
    return _default_decoder.decode(s)
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

Puede remediar comprobando si json_stringestá vacío de antemano:

import json

if json_string:
    x = json.loads(json_string)
else:
    // Your logic here
    x = {}
Alex W
fuente
Mientras depuraba más arriba en mi código, estaba llamando response.read()y luego me desanimé cuando otra llamada resultó en Expecting value: line 1etc. Se eliminó la declaración de depuración y se resolvió el problema.
Joe
Para depurar, también puede usar este buen sitio web jsonlint.com
Roelant
4

Puede haber 0 incrustados, incluso después de llamar a decode (). Utilice replace ():

import json
struct = {}
try:
    response_json = response_json.decode('utf-8').replace('\0', '')
    struct = json.loads(response_json)
except:
    print('bad json: ', response_json)
return struct
Bryan
fuente
2

Tuve exactamente este problema usando las solicitudes. Gracias a Christophe Roussy por su explicación.

Para depurar, usé:

response = requests.get(url)
logger.info(type(response))

Estaba recibiendo una respuesta 404 de la API.

Kelsie Braidwood
fuente
1
Se puede simplificar a response.status_codeo print(response.status_code).
TitanFighter
1

Estaba teniendo el mismo problema con las solicitudes (la biblioteca de Python). Resultó ser el accept-encodingencabezado.

Se estableció de esta manera: 'accept-encoding': 'gzip, deflate, br'

Simplemente lo eliminé de la solicitud y dejé de recibir el error.

Seu Madruga
fuente
1

Para mí, no estaba usando autenticación en la solicitud.

Neel0507
fuente
1

Para mí, el servidor respondía con algo diferente a 200 y la respuesta no tenía formato json. Terminé haciendo esto antes del análisis json:

# this is the https request for data in json format
response_json = requests.get() 

# only proceed if I have a 200 response which is saved in status_code
if (response_json.status_code == 200):  
     response = response_json.json() #converting from json to dictionary using json library
FastGTR
fuente
Este fue el problema para mí. El código de estado era 500 (error interno del servidor) en lugar de 200, por lo que no se devolvió json y, por lo tanto, no había nada en la línea 1 col 1 de json. Siempre es bueno comprobar que el código de estado de la solicitud es el que espera que sea.
thposs
1

Encontré el mismo problema, mientras imprimía la cadena json abierta desde un archivo json, encontré que la cadena json comienza con 'ï »¿', que al hacer un poco de investigación se debe a que el archivo se decodifica por defecto con UTF-8, y Al cambiar la codificación a utf-8-sig, la marca se elimina y se carga json sin problema:

open('test.json', encoding='utf-8-sig')
usuario9571515
fuente
0

Si es usuario de Windows, la API Tweepy puede generar una línea vacía entre los objetos de datos. Debido a esta situación, puede obtener el error "JSONDecodeError: valor esperado: línea 1 columna 1 (char 0)". Para evitar este error, puede eliminar líneas vacías.

Por ejemplo:

 def on_data(self, data):
        try:
            with open('sentiment.json', 'a', newline='\n') as f:
                f.write(data)
                return True
        except BaseException as e:
            print("Error on_data: %s" % str(e))
        return True

Referencia: la API de transmisión de Twitter proporciona JSONDecodeError ("Valor esperado", s, err.value) de Ninguno

drorhun
fuente
No creo que las líneas vacías sean un problema. Establece claramente que el error está en la línea 1, columna 1. Creo que esta solución funciona porque está eliminando la lista de materiales del archivo. Puede verificarlo rápidamente: 1. Verifique el tamaño de su archivo original (clic derecho> Propiedades), puede ser 134.859 bytes 2. Abra el archivo original con Notepad ++ 3. Cambie la codificación de "UTF-8-BOM" a " UTF-8 ". Guardar 4. Verifique el tamaño nuevamente. Puede ser 134.856 (3 bytes menos)
Alex 75
0

Simplemente verifique si la solicitud tiene un código de estado 200. Entonces, por ejemplo:

if status != 200:
    print("An error has occured. [Status code", status, "]")
else:
    data = response.json() #Only convert to Json when status is OK.
    if not data["elements"]:
        print("Empty JSON")
    else:
        "You can extract data here"
Wout VC
fuente
0

Recibí dicho error en la respuesta de una API web basada en Python .text, pero me trajo aquí, por lo que esto puede ayudar a otros con un problema similar (es muy difícil filtrar la respuesta y solicitar problemas en una búsqueda cuando se usa requests...)

El uso json.dumps()del argumento de solicitud data para crear una cadena de JSON con escape correcto antes de PUBLICAR me solucionó el problema

requests.post(url, data=json.dumps(data))
ti7
fuente