Python Запросы: Обработка JSON ответа, сохранение в список или дикт? - PullRequest
2 голосов
/ 05 февраля 2020

Я использую библиотеку запросов python, чтобы получить данные из API. Данные возвращаются в большом массиве json, называемом сообщениями. В нем содержится много отдельных jsons подуровня «message» (см. Образец ответа json внизу).

В этом ответе json для каждого сообщения есть только несколько (2 или 3) точек данных, которые меня волнуют. Мне нужно взять эти несколько точек данных и сохранить их во что-либо (список, словарь и т. Д. c.), Чтобы я мог ссылаться на них позже, сохранять в объекте и использовать из другой функции.

Точки данных, которые мне нужно сохранить: id, conversationId и body. The id is unique, while the dialogId` совместно используются всеми сообщениями в беседе, поэтому не являются уникальными.

  1. Сначала я хотел бы спросить, как вы думаете, как лучше всего это сделать. Я угадываю список списков или словарь списков? Я слишком новичок, чтобы знать, что было бы лучшим решением.
  2. Кроме того, какой бы метод ни был выбран, мне нужно будет знать, как ссылаться на них и вызывать их по id для сохранения объекта из другой функции. Мне еще предстоит выяснить, как это сделать успешно.

Вот несколько вещей, которые я попытался просто получить общее представление о том, как я могу это сделать:

response=requests.get(url + id, headers=h, params=p)
messages=json.loads(response.text)
for message in messages:
    print(message['body'])

^^ здесь я просто пытаюсь увидеть, могу ли я сослаться на конкретное c тело сообщения, не сработало.

r=requests.get(url + id, headers=h, params=p)
inbound_dict = {}
inbound=json.loads(r.text)
for item in inbound['messages']:
    inbound_dict[item['conversationId']] = item['body']
print(inbound_dict)

^^ Это на самом деле работает несколько, но не позволяет мне организовать данные эффективно, чтобы позвонить позже. когда я печатаю словарь, он показывает мне новейшее значение, потому что ключ не уникален ... поэтому он перезаписывается, а не добавляется. Это то, что заставляет меня думать, что список списков был бы лучшим.

В конце я хочу решение, где данные организованы по conversationId в словаре или что-то подобное со структурой, подобной этой, где Я могу ссылаться на сообщения по conversationId, или msgId, и легко читаемый способ хранения всего этого ... :)

Messages
     |___                  msgId:
         |_conversationId-[
         |                 body
         |                 msgId:
         |_conversationId-[
         |                 body
         |                 msgId:
         |_conversationId-[
                           body

Наконец, вот пример json , Пожалуйста, имейте в виду, что я все еще учусь и набираю скорость с python. Спасибо всем за потраченное время!

b'{"id":1005672,"messages":[{"id":4461048,"body":"Mnow test test","conversationId":1005672,"locationId":2045,"contactId":12792806,"assignedUserId":0,"status":"RECEIVED","error":null,"kind":"INCOMING","outgoing":false,"reviewRequest":false,"type":"SMS","readDate":0,"respondedDate":0,"sentDate":1576783232355,"attachments":[]},{"id":4461049,"body":"THIS NUMBER DOES NOT CURRENTLY ACCEPT TEXT MESSAGES PLEASE CALL (716) 444-4444 TO WORK WITH ONE OF OUR INTAKE SPECIALISTS","conversationId":1005672,"locationId":2045,"contactId":12792806,"assignedUserId":0,"status":"RECEIVED","error":null,"kind":"AUTO_RESPONSE","outgoing":true,"reviewRequest":false,"type":"SMS","readDate":0,"respondedDate":0,"sentDate":1576783233546,"attachments":[]},{"id":4620511,"body":"test sms,test sms","conversationId":1005672,"locationId":2045,"contactId":12792806,"assignedUserId":17297,"status":"DELIVERED","error":null,"kind":"API","outgoing":true,"reviewRequest":false,"type":"SMS","readDate":0,"respondedDate":0,"sentDate":1577987093930,"attachments":[]},...

enter image description here

Ответы [ 3 ]

1 голос
/ 05 февраля 2020

Вы можете сделать это с помощью комбинирования списка и словаря, например, так:

import json
from pprint import pprint


response = b'{"id":1005672,"messages":[{"id":4461048,"body":"Mnow test test","conversationId":1005672,"locationId":2045,"contactId":12792806,"assignedUserId":0,"status":"RECEIVED","error":null,"kind":"INCOMING","outgoing":false,"reviewRequest":false,"type":"SMS","readDate":0,"respondedDate":0,"sentDate":1576783232355,"attachments":[]},{"id":4461049,"body":"THIS NUMBER DOES NOT CURRENTLY ACCEPT TEXT MESSAGES PLEASE CALL (716) 444-4444 TO WORK WITH ONE OF OUR INTAKE SPECIALISTS","conversationId":1005672,"locationId":2045,"contactId":12792806,"assignedUserId":0,"status":"RECEIVED","error":null,"kind":"AUTO_RESPONSE","outgoing":true,"reviewRequest":false,"type":"SMS","readDate":0,"respondedDate":0,"sentDate":1576783233546,"attachments":[]},{"id":4620511,"body":"test sms,test sms","conversationId":1005672,"locationId":2045,"contactId":12792806,"assignedUserId":17297,"status":"DELIVERED","error":null,"kind":"API","outgoing":true,"reviewRequest":false,"type":"SMS","readDate":0,"respondedDate":0,"sentDate":1577987093930,"attachments":[]}]}'

data = json.loads(response)

messages = [
    {'id': message['id'],
     'conversationId': message['conversationId'],
     'body': message['body']} for message in data['messages']
]

pprint(messages, sort_dicts=False)

Вывод:

[{'id': 4461048, 'conversationId': 1005672, 'body': 'Mnow test test'},
 {'id': 4461049,
  'conversationId': 1005672,
  'body': 'THIS NUMBER DOES NOT CURRENTLY ACCEPT TEXT MESSAGES PLEASE CALL '
          '(716) 444-4444 TO WORK WITH ONE OF OUR INTAKE SPECIALISTS'},
 {'id': 4620511, 'conversationId': 1005672, 'body': 'test sms,test sms'}]

Вы можете сделать что-то большее для обработки данных и устранить много повторяющихся кодов в понимании, чтобы сделать его еще более лаконичным, делая это так:

import json
from pprint import pprint

data_points = 'id', 'conversationId', 'body'
response = b'{"id":1005672,"messages":[{"id":4461048,"body":"Mnow test test","conversationId":1005672,"locationId":2045,"contactId":12792806,"assignedUserId":0,"status":"RECEIVED","error":null,"kind":"INCOMING","outgoing":false,"reviewRequest":false,"type":"SMS","readDate":0,"respondedDate":0,"sentDate":1576783232355,"attachments":[]},{"id":4461049,"body":"THIS NUMBER DOES NOT CURRENTLY ACCEPT TEXT MESSAGES PLEASE CALL (716) 444-4444 TO WORK WITH ONE OF OUR INTAKE SPECIALISTS","conversationId":1005672,"locationId":2045,"contactId":12792806,"assignedUserId":0,"status":"RECEIVED","error":null,"kind":"AUTO_RESPONSE","outgoing":true,"reviewRequest":false,"type":"SMS","readDate":0,"respondedDate":0,"sentDate":1576783233546,"attachments":[]},{"id":4620511,"body":"test sms,test sms","conversationId":1005672,"locationId":2045,"contactId":12792806,"assignedUserId":17297,"status":"DELIVERED","error":null,"kind":"API","outgoing":true,"reviewRequest":false,"type":"SMS","readDate":0,"respondedDate":0,"sentDate":1577987093930,"attachments":[]}]}'
data = json.loads(response)
messages = [{dp: message.get(dp) for dp in data_points}
                for message in data['messages']]

pprint(messages, sort_dicts=False)
1 голос
/ 05 февраля 2020

Насколько я понимаю, вы хотите, чтобы ваши сообщения в структуре данных были доступны для разговора. Вот что я хотел бы сделать:

from pprint import pprint

#with this data structure whenever we refer to a conversation, if it
#doesn't exist, it gets created
from collections import defaultdict
inbound_dict = defaultdict(dict) 

inbound=json.loads(data)
for item in inbound['messages']:
    print (item)

    current_conversation=inbound_dict[item['conversationId']]
    #inbound_dict retrives the apropriate conversation,
    #   or creates a new one for us to fill
    current_conversation[item["id"]] = item['body'] #add our item to it.

    #or if there's a chance we might want *everything* else about the
    #message later even if just the date in order to preserve
    #conversation ordering or whatever:

    #currentconversation[item["id"]] = item

pprint(inbound_dict)

Но это может быть излишним, в зависимости от того, какую обработку вы собираетесь делать позже, и какую обработку это будет. Если вы просто позволите им выбрать беседу и отобразить последние 20 сообщений, список с возможностью среза может быть лучшим выбором для внутренней структуры данных, и в этом случае я бы сделал следующее:

from pprint import pprint

#with this data structure whenever we refer to a conversation, if it
#doesn't exist, it gets created
from collections import defaultdict
inbound_dict = defaultdict(list) 

inbound=json.loads(data)
for item in inbound['messages']:
    print (item)

    current_conversation=inbound_dict[item['conversationId']]
    #inbound_dict retrives the apropriate conversation,
    #   or creates a new one for us to fill

    current_conversation.append(
        (item["id"], item['body'])
        ) # here we add our item to it, in this case a tuple of id and body

    #or if there's a chance we might want *everything* else about the
    #message later even if just the date in order to preserve
    #conversation ordering or whatever:

    #currentconversation.append(item)

pprint(inbound_dict)

В основном та же операция, но с defaultdict, предоставляя нам другой тип внутренней коллекции для заполнения.

0 голосов
/ 05 февраля 2020

если у вас может быть несколько элементов с одним и тем же параметром разговор_, тогда вы можете сделать что-то вроде этого:

r=requests.get(url + id, headers=h, params=p).json()
inbound_dict = {}
for item in r['messages']:
    conv_id = item['conversationId']
    if conv_id not in inbound_dict:
        inbound_dict[conv_id]=[{'msg_id' : item['id'], 'body' : item['body']}]
    else:
        inbound_dict[conv_id].append({'msg_id' : item['id'], 'body' : item['body']})

print(inbound_dict)

Получившаяся структура данных представляет собой словарь с ключом разговора в качестве ключей, и каждый разговор_ид отображается на list из dict предметов. каждый элемент хранит message_id и тело конкретного сообщения. Затем вы можете перебирать сообщения для конкретного разговора, получая список сообщений, сохраненных для ключа conv_id.

В качестве альтернативы вы можете выбрать следующую структуру данных для сопоставления: {conv_id -> { message_id : {message info ...}, ...}.

Это может быть реализовано следующим образом:

r=requests.get(url + id, headers=h, params=p).json()
inbound_dict = {}
for item in r['messages']:
    conv_id = item['conversationId']
    if conv_id not in inbound_dict:
        inbound_dict[conv_id]={item['id'] : {'msg_id' : item['id'], 'body' : item['body']}}
    else:
        inbound_dict[conv_id][item['id']] = {'msg_id' : item['id'], 'body' : item['body']}

print(inbound_dict)

В этом случае вы можете получить доступ к сообщению напрямую из беседы, если вам известны con_id и message_id.

это действительно зависит от нисходящей утилиты для этой структуры данных.

Обратите внимание, что вышеизложенное может быть достигнуто и со списком.

...