web-dev-qa-db-fra.com

Objet HTTPResponse - L'objet JSON doit être str, pas 'octets'

J'ai essayé de mettre à jour une petite bibliothèque Python appelée libpynexmo pour fonctionner avec Python 3.

J'ai été bloqué sur cette fonction:

def send_request_json(self, request):
    url = request
    req =  urllib.request.Request(url=url)
    req.add_header('Accept', 'application/json')
    try:
        return json.load(urllib.request.urlopen(req))
    except ValueError:
        return False

Quand cela arrive, json répond:

TypeError: the JSON object must be str, not 'bytes'

J'ai lu à quelques endroits que pour json.load, Vous devez passer des objets (dans ce cas, un objet HTTPResponse) avec une .read() attachée, mais cela ne fonctionne pas sur HTTPResponse objets.

Je ne sais pas où aller avec ça ensuite, mais étant donné que mon script de 1500 lignes est fraîchement converti en Python 3, je n'ai pas envie de revenir à 2.7.

26
Chevron

J'ai récemment écrit une petite fonction pour envoyer des messages Nexmo. À moins que vous n'ayez besoin de toutes les fonctionnalités du code libpynexmo, cela devrait faire le travail pour vous. Et si vous souhaitez continuer à réviser libpynexmo, copiez simplement ce code. La clé est le codage utf8.

Si vous souhaitez envoyer d'autres champs avec votre message, la documentation complète de ce que vous pouvez inclure avec un message sortant nexmo est ici

Python 3.4 testé Nexmo sortant (JSON):

def nexmo_sendsms(api_key, api_secret, sender, receiver, body):
    """
    Sends a message using Nexmo.

    :param api_key: Nexmo provided api key
    :param api_secret: Nexmo provided secrety key
    :param sender: The number used to send the message
    :param receiver: The number the message is addressed to
    :param body: The message body
    :return: Returns the msgid received back from Nexmo after message has been sent.
    """


    msg = {
        'api_key': api_key,
        'api_secret': api_secret,
        'from': sender,
        'to': receiver,
        'text': body
    }
    nexmo_url = 'https://rest.nexmo.com/sms/json'
    data = urllib.parse.urlencode(msg)
    binary_data = data.encode('utf8')
    req = urllib.request.Request(nexmo_url, binary_data)
    response = urllib.request.urlopen(req)
    result = json.loads(response.readall().decode('utf-8'))
    return result['messages'][0]['message-id']
18
Ryan

Face au même problème, je le résous en utilisant decode ()

...
rawreply = connection.getresponse().read()
reply = json.loads(rawreply.decode())
47
costas

J'ai aussi rencontré le problème et maintenant ça passe

import json
import urllib.request as ur
import urllib.parse as par

html = ur.urlopen(url).read()
print(type(html))
data = json.loads(html.decode('utf-8'))
12
Du Peng

Puisque vous obtenez un HTTPResponse , vous pouvez utiliser Tornado.escape et sa json_decode() pour convertir le strign JSON en dictionnaire:

from tornado import escape

body = escape.json_decode(body)

Du manuel:

tornado.escape.json_decode (valeur)

Renvoie Python objets pour la chaîne JSON donnée.

2
fedorqui