「slackのAPIを利用して、リアクションを押下していない人に対してメンション」で分かったこと【主にjsonについて】

##概要
表題の通り。
主にpythonでjsonを扱う際に何に気をつけるべきかをまとめる。

##やりたかったこと（下記の画像の通り。）
①slackのメンバーを取得（member_list.py）
②定時起動で出勤に合わせて、APIでメッセージを送信。(postMessage.py)
③メンバーがリアクション。
④APIで上記②にリアクションをした人を取得。（reac_result.py）
⑤リアクションを押下していないリストを作成。
⑥上記⑤で作成したリストに対してAPIでメンション。（postMessage_re.py）

![01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630898/74151a1f-afe9-4eb1-f213-6ca31d5e2bdd.jpeg)

#わかったこと抜粋（①、②、④、⑤、⑥）
##①でのコード抜粋、わかったこと
■辞書（dict型オブジェクト）の値はkeyで選択して抽出できること
 下記のコードではgetしたresponseから名前を抜き出そうとしている。

```def_member_list.py
    r = requests.get(url, params=payload)
    result_mem = []  # 結果を入れるリストを用意
    json_data = r.json()
    members = json_data["members"] 
    for i in members:
        result_mem.append(i["real_name"])# 結果を追加
    ppront.pprint(result_mem)#['Slackbot']
```

```json_data.
#json_dataには以下のようなデータが格納されている。
｛"ok": true,
"members": [ {"id": "USLACKBOT","team_id": "T012YMJ67V1","real_name": "Slackbot"
```

>d = {'key1': 'aaa', 'key2': 'bbb', 'key3': 'ccc'}
value = d['key1']
print(value) #aaa
つまり{"key" : value,}

**なので、value（"Slackbot"）を取得したい場合は、key("real_name")を指定する。**

##②でのコード抜粋、わかったこと
■関数から関数の呼び出し元へ任意の値を返す場合には returnを使用すればよいこと
 下記のコードではgetしたresponseからタイムスタンプを抜き出そうとしている。

```def_postMessage.py
def postMessage():
    r = requests.post(url, params=payload)
    result_text = []  # 結果を入れるリストを用意
    json_data = r.json()
    ts = json_data['ts']
    return (ts)
```
```postMessage.py
import datetime
import def_postMessage
a = def_postMessage.postMessage()
with open(str(datetime.date.today())+'_ts.txt', mode='a') as f:
    print(a,file=f)
```
def_postMessage.pyで取得したts(タイムスタンプ)が戻り値で、それをpostMessage.pyが使用している。
slackではtsが一意なのでメッセージを特定することができる。

##④でのコード抜粋、わかったこと
■ネスト（入れ子）の時、値を取得したい場合は、JSONの構造を理解する必要があること
■参考は[ここのサイト](https://developer.mozilla.org/ja/docs/Learn/JavaScript/Objects/JSON)
■returnでの戻り値には、変数を指定できること
下記のコードではgetしたresponseからリアクションをした人を抽出しようとしている。

```def_reaction.py
def reaction():
    r = requests.get(url, params=payload)
    json_data = r.json()
    reac_tmp1 = json_data['messages'][0]['reactions'][0]['users']
    reac_tmp2 = json_data['messages'][0]['reactions'][1]['users']
    reac_tmp3 = json_data['messages'][0]['reactions'][2]['users']
return(reac_tmp1,reac_tmp2,reac_tmp3)
```

```json_data.
{'channel_actions_count': 0,
 'channel_actions_ts': None,
 'messages': [{'bot_id': 'B012YMHEVJN',
               'bot_profile': {'app_id': 'A0134SP1ZA8',
                               'id': 'B012YMHEVJN',
                               'name': 'test',
                               'team_id': 'T012YMJ67V1',
               'reactions': [{'count': 3,
                              'name': 'syukkin',
                              'users': ['U012JDYRD2T',
                                        'U013BQDLK6V',
                                        'U012ZC8AQ8K']},
                             {'count': 2,
                              'name': 'tikoku',
                              'users': ['U012XQBE63X', 'U012JDYSN07']},
                             {'count': 1,
                              'name': 'kekkin',
                              'users': ['U012JDYSN07']}]
```

---
■やっていること（`reac_tmp1 = json_data['messages'][0]['reactions'][0]['users']`の場合）
①変数名json_data を指定
②その中の'messages'プロパティへアクセスしたいので、`["messages"]`と指定。
③messages にはオブジェクトの配列が格納。 ここでは、配列内の 1番目のオブジェクトへアクセスするので、`[0]`を指定。(【'messages': [{'bot_id'】云々の以下すべてにアクセス)
④そのオブジェクト内で'reactions'プロパティへアクセスするため,` ["reactions"]`と指定。
⑤その中の1番目が欲しいので、`[0]`と記述。(2番目が欲しいときは[1]、3番目が欲しいときは[2])
⑥そのオブジェクト内で'users'プロパティへアクセスするため, `["users"]`と指定。

つまり
**送信したメッセージのリアクション（reactions）をしたメンバー（users）がreac_tmpに格納されている。**
（reac_tmp1-3まであるのは、【出勤】【遅刻】【欠勤】と3つあり、この3つのリアクションをした人が誰かを知りたいから。）

##⑤でのコード抜粋、わかったこと
別記事で投稿。
https://qiita.com/nonono_kita/items/588ad61431e97724deab


##⑥でのコード抜粋、わかったこと
別記事で投稿。
https://qiita.com/nonono_kita/items/e83a3b918aa572b69adf

##今後やりたいこと、できそうなこと
・エラー時のための条件分岐。
・DBを用意、リアクションを押下したメンバーの情報をもとに、更新をかける処理。
・更新処理後、リアクションを押下していない人に、メンションする処理。

##課題
■条件分岐を用意していない。そのため
　・メッセージにリアクションがないとエラー
　・メッセージにリアクションが少ないとエラー
　・出力したファイルが存在しないとエラー
　・出力したファイル名が異なるとエラー

##思ったこと
　・jsonでデータを取得した際に、その関数や処理内でデータを加工するよりは一度データに出力した方がよさそう。
　　出力して、そのあとに必要なデータを加工。その方が関数を使いまわせそう。
　・あと記事が長くなるので、項目ごとに記事を書いた方が良いかもしれない。