Пусть объект JSON принимает байты или позволяет выводить строки вывода
С Python 3 я запрашиваю json-документ из URL-адреса.
response = urllib.request.urlopen(request)
response
объект представляет собой файл-подобный объект для read
и readline
методов. Обычно объект JSON может быть создан с файлом, открытым в текстовом режиме.
obj = json.load(fp)
Я бы хотел:
obj = json.load(response)
Однако это не работает, поскольку urlopen возвращает файл-объект в двоичном режиме.
Разумеется, работа вокруг:
str_response = response.read().decode('utf-8')
obj = json.loads(str_response)
но это плохо...
Есть ли лучший способ, которым я могу преобразовать объект байтового файла в объект строкового файла? Или мне не хватает каких-либо параметров для urlopen
или json.load
чтобы дать кодировку?
Ответы
Ответ 1
HTTP отправляет байты. Если рассматриваемый ресурс является текстом, кодировка символов обычно указывается либо заголовком HTTP-типа контента, либо другим механизмом (RFC, HTML meta http-equiv
,...).
urllib
должен знать, как закодировать байты в строке, но это слишком наивно - это ужасно малоизученная и непифоническая библиотека.
Dive Into Python 3 содержит обзор ситуации.
Ваша "работа" - это хорошо, хотя кажется, что это неправильно, это правильный способ сделать это.
Ответ 2
Pythons замечательная стандартная библиотека для спасения...
import codecs
reader = codecs.getreader("utf-8")
obj = json.load(reader(response))
Работает как с py2, так и с py3.
Документы: Python 2, Python3
Ответ 3
Я пришел к мнению, что вопрос - лучший ответ:)
import json
from urllib.request import urlopen
response = urlopen("site.com/api/foo/bar").read().decode('utf8')
obj = json.loads(response)
Ответ 4
Для других, кто пытается решить это, используя библиотеку requests
:
import json
import requests
r = requests.get('http://localhost/index.json')
r.raise_for_status()
# works for Python2 and Python3
json.loads(r.content.decode('utf-8'))
Ответ 5
Это работает для меня, я использовал библиотеку "запрос" с json()
, чтобы проверить документ в запросы для людей
import requests
url = 'here goes your url'
obj = requests.get(url).json()
Ответ 6
Я столкнулся с аналогичными проблемами, используя Python 3.4.3 и 3.5.2 и Django 1.11.3. Однако, когда я обновился до Python 3.6.1, проблемы ушли.
Подробнее об этом можно узнать здесь: https://docs.python.org/3/whatsnew/3.6.html#json
Если вы не привязаны к определенной версии Python, просто подумайте об обновлении до версии 3.6 или новее.
Ответ 7
Если вы столкнулись с этой проблемой при использовании микрофотографии в колбе, вы можете просто сделать:
data = json.loads(response.get_data(as_text=True))
Из документов: "Если as_text установлено в True, возвращаемое значение будет декодированной строкой Unicode"
Ответ 8
Ваше обходное решение на самом деле просто спасло меня. У меня возникло множество проблем с обработкой запроса с использованием инфраструктуры Falcon. Это сработало для меня. req является формой запроса curl pr httpie
json.loads(req.stream.read().decode('utf-8'))
Ответ 9
Просто нашел этот простой способ сделать контент HttpResponse как json
import json
request = RequestFactory() # ignore this, this just like your request object
response = MyView.as_view()(request) # got response as HttpResponse object
response.render() # call this so we could call response.content after
json_response = json.loads(response.content.decode('utf-8'))
print(json_response) # {"your_json_key": "your json value"}
Надеюсь, что поможет вам
Ответ 10
Это приведет к потоку данных байта в json.
import io
obj = json.load(io.TextIOWrapper(response))
io.TextIOWrapper предпочтительнее считывателя модуля кодека. https://www.python.org/dev/peps/pep-0400/
Ответ 11
Начиная с Python 3.6, вы можете использовать json.loads()
для десериализации объекта bytes
напрямую (кодировка должна быть UTF-8, UTF-16 или UTF-32). Итак, используя только модули из стандартной библиотеки, вы можете сделать:
import json
from urllib import request
response = request.urlopen(url).read()
data = json.loads(response)
Ответ 12
Я использовал ниже программу для использования json.loads()
import urllib.request
import json
endpoint = 'https://maps.googleapis.com/maps/api/directions/json?'
api_key = 'AIzaSyABbKiwfzv9vLBR_kCuhO7w13Kseu68lr0'
origin = input('where are you ?').replace(' ','+')
destination = input('where do u want to go').replace(' ','+')
nav_request = 'origin={}&destination={}&key={}'.format(origin,destination,api_key)
request = endpoint + nav_request
response = urllib.request.urlopen(request).read().decode('utf-8')
directions = json.loads(response)
print(directions)