Какой самый Pythonic способ выделить это значение из JSON-подобного большого двоичного объекта? - PullRequest
2 голосов
/ 30 июня 2019

Смотри ниже.Учитывая известный URL Google, я пытаюсь получить данные с этого URL.Эти данные предоставят мне еще один URL-адрес Google, с которого я смогу получить список JWK.

>>> import requests, json
>>> open_id_config_url = 'https://ggp.sandbox.google.com/.well-known/openid-configuration'
>>> response = requests.get(open_id_config_url)
>>> r.status_code
200

>>> response.text
u'{\n "issuer": "https://www.stadia.com",\n "jwks_uri": "https://www.googleapis.com/service_accounts/v1/jwk/stadia-jwt@system.gserviceaccount.com",\n "claims_supported": [\n  "iss",\n  "aud",\n  "sub",\n  "iat",\n  "exp",\n  "s_env",\n  "s_app_id",\n  "s_gamer_tag",\n  "s_purchase_country",\n  "s_current_country",\n  "s_session_id",\n  "s_instance_ip",\n  "s_restrict_text_chat",\n  "s_restrict_voice_chat",\n  "s_restrict_multiplayer",\n  "s_restrict_stream_connect",\n ],\n "id_token_signing_alg_values_supported": [\n  "RS256"\n ],\n}'

Выше я успешно извлек данные из первого URL-адреса.Я вижу, что запись jwks_uri содержит второй URL-адрес, который мне нужен.Но когда я пытаюсь преобразовать этот фрагмент текста в словарь Python, он терпит неудачу.

>>> response.json()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/saqib.ali/saqib-env-99/lib/python2.7/site-packages/requests/models.py", line 889, in json
    self.content.decode(encoding), **kwargs
  File "/usr/local/Cellar/python@2/2.7.16/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 339, in loads
    return _default_decoder.decode(s)
  File "/usr/local/Cellar/python@2/2.7.16/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 364, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/local/Cellar/python@2/2.7.16/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 382, in raw_decode
    raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded

>>> json.loads(response.text)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/python@2/2.7.16/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 339, in loads
    return _default_decoder.decode(s)
  File "/usr/local/Cellar/python@2/2.7.16/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 364, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/local/Cellar/python@2/2.7.16/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 382, in raw_decode
    raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded

Единственный способ получить URL-адрес JWK - это выполнить ужасный анализ регулярного выражения:

>>> re.compile('(?<="jwks_uri": ")[^"]+').findall(response.text)[0]
u'https://www.googleapis.com/service_accounts/v1/jwk/stadia-jwt@system.gserviceaccount.com'

Существует ли более чистый и более питонский способ извлечения этой строки?Я действительно хотел бы, чтобы Google отправил обратно строку, которая могла бы быть чисто JSON-ified.

Ответы [ 3 ]

4 голосов
/ 30 июня 2019

Возвращенная строка json неверна, потому что последний элемент словаря оканчивается на ,, что json не может проанализировать.

": [\n  "RS256"\n ],\n}'
                  ^^^

Но ast.literal_eval может это сделать (так как синтаксический анализатор python принимает списки / дикты)это конец с запятой).Пока у вас нет логических или null значений, возможно и питонное

>>> ast.literal_eval(response.text)["jwks_uri"]
'https://www.googleapis.com/service_accounts/v1/jwk/stadia-jwt@system.gserviceaccount.com'
2 голосов
/ 30 июня 2019

Ваш JSON недопустим, поскольку у него есть лишняя запятая после последнего значения в массиве claims_supported.

Я бы не рекомендовал его, но вы можете использовать сходство синтаксиса JSON и Python дляразберите это напрямую, так как Python гораздо менее требователен:

ast.literal_eval(response.tezt)
1 голос
/ 01 июля 2019

Как указано в в этом ответе , используйте yaml для анализа json.Он будет допускать запятую, а также другие отклонения от стандарта json.

import yaml

d = yaml.load(response.text)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...