@sonblet

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

GASでjsonの値をうまく取り出せない

解決したいこと

以下のような勤怠管理botをGASで作っています。
GASでSlackに勤怠確認フォーマット(何時に出勤したの?)を送る
→Slackから送信したデータ(*時に出勤したよ!)をjson形式で受け取る
→ユーザー名や出勤時間などを取り出してスプレッドシートに転記する
ユーザー名を取り出すところまではできたのですが、
どうしても取り出し方がわからないデータがあり、進めなくなってしまいました。
数時間ほどいろいろ試してみましたが、どうにもなりません・・・
解決方法を教えてください。

発生している問題・エラー

{
…(略)…

user={team_id=ABCD, username=suzuki, name=suzuki, id=XXXX},
↑この中身は取り出せる

state={
 values={
  LL20h={timepicker-action={selected_time=09:00, type=timepicker}},
  t0C={plain_text_input-action={type=plain_text_input, value=明日休みます}}
 }
},
↑この中身が取り出せない。”LL20h”などの変数?をどう扱えばよいかわかりません・・・

…(略)…

}

該当するソースコード

function doPost(e) {

const payload = JSON.parse(e['parameter']['payload']);
const name = payload.user.name;
const answers = payload.state.values;

var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シート1');

sheet.getRange(1, 1).setValue(payload);
sheet.getRange(1, 2).setValue(name);
sheet.getRange(1, 3).setValue(answers); ←ここまでは問題なし

let comment = '';
let time = '';

for (key in answers) {
if (answers[key].hasOwnProperty('plain_text_input-action')) {
sheet.getRange(1, 4).setValue('Y');
comment = answers.key.plain_text_input-action.value;

} else if (answers[key].hasOwnProperty('timepicker-action')) {
  for (const timepicker of answers[key].timepicker-action.selected_time) {
    time += timepicker.selected_time;
    sheet.getRange(1, 5).setValue(time);

  }
}

}

}

自分で試したこと

ソースコードにあるように変数に入れてみたりしたのですが全然ダメでした・・・
アドバイスしていただけると嬉しいです。

0 likes

3Answer

冗長ですが、元のコードから変更を極力少なくした場合のコードです。
※コメントにあるように、selected_time の値は配列ではない、とのことなので、配列ではない場合に限り動作します。
またJSONの構造(キー名や値は変わってもよい)が記載されているものと異なる場合は、動作しない可能性があります。(取得したい値やその途中のパスに配列が含まれている場合等)
修正前

  for (key in answers) {
    if (answers[key].hasOwnProperty('plain_text_input-action')) {
      sheet.getRange(1, 4).setValue('Y');
      comment = answers.key.plain_text_input-action.value;
    } else if (answers[key].hasOwnProperty('timepicker-action')) {
      for (const timepicker of answers[key].timepicker-action.selected_time) {
        time += timepicker.selected_time;
        sheet.getRange(1, 5).setValue(time);
      }
    }
  }

ここを以下のように直してみてください。

修正後


  for (const key in answers) {
    if (answers[key].hasOwnProperty('plain_text_input-action')) {
      for (const key_plain_text_input in answers[key]['plain_text_input-action']) {
        if (key_plain_text_input === 'value') {
          sheet.getRange(1, 4).setValue('Y');
          comment = answers[key]['plain_text_input-action'].value;
          break;
        }
      }
    } else if (answers[key].hasOwnProperty('timepicker-action')) {
      for (const key_timepicker in answers[key]['timepicker-action']) {
        if (key_timepicker === 'selected_time') {
          time += answers[key]['timepicker-action'].selected_time;
          sheet.getRange(1, 5).setValue(time);
          break;
        }
      }
    }
  }

実際は、再帰を使ったコードの方がスマートですし汎用性もあると思いますがここでは割愛します。

1Like

Comments

  1. @sonblet

    Questioner

    すごいです!教えていただいたコードで動作しました!本当にありがとうございます!!!
    アドバイスいただけなかったらずっと解決できなかったと思います涙
    知識不足でいろいろとご面倒をおかけしたのに(あれがjsonフォーマットだと思っていました・・・)親切にお付き合いくださって、感謝の気持ちでいっぱいです。
    どこがダメだったのか自分なりに調べてみて、再帰を使ったコードにできないかも試してみたいと思います。
    本当にありがとうございました!!!

selected_time の中身が配列になっているパターンもあるのですか?その場合、どのようなJSONになるのでしょうか。今の質問文だと、情報が少なすぎます。

0Like

Comments

  1. @sonblet

    Questioner

    selected_timeは一つしか選べないため、配列になっているパターンはないです。
  2. @sonblet

    Questioner

    情報量が少なくてすみません!jsonを全部載せればよいでしょうか?
  3. そうですね「JSONフォーマットの文字列」をそのまま載せてほしいです(今だとキーと値が「=」でつながっていたり、キー名が引用符で囲まれていません=JSONフォーマットでないので、いちいち自分でJSONに書き換えないといけないので試すにも面倒です)
  4. @sonblet

    Questioner

    ありがとうございます!一部XXXXに置き換えてますが、これが全部です。

    {
    channel={
    name=directmessage,
    id=XXXX
    },
    message={
    blocks=[Ljava.lang.Object;@78b8deec,
    type=message,
    subtype=bot_message,
    ts=XXXX,
    bot_id=XXXX,
    text=This content can't be displayed.
    },
    team={
    domain=XXXX,
    id=XXXX,
    },
    actions=[Ljava.lang.Object;@7a60494c,
    is_enterprise_install=false,
    container={
    message_ts=XXXX,
    is_ephemeral=false,
    type=message,
    channel_id=XXXX,
    },
    trigger_id=XXXX,
    token=XXXX,
    enterprise=null,
    state={
    values={
    LL20h={
    timepicker-action={
    selected_time=02:00,
    type=timepicker
    }
    },
    t0C={
    plain_text_input-action={
    type=plain_text_input,
    value=こんにちは
    }
    }
    }
    },
    user={
    team_id=XXXX,
    username=suzuki,
    name=suzuki,
    id=XXXX
    },
    response_url=https://XXXX
    type=block_actions,
    api_app_id=XXXX
    }
  5. 「JSONフォーマットで」って言ったんですがね・・・。まあいいです。

Your answer might help someone💌