階層化されたjsonデータをフラットな連想配列に変換してからスプレッドシートに記入する方法をChatGPTさんに教えてもらったのでシェア。
完成したソースコード
function writeJsonToSheet(jsonData, sheetname) {
// 記入するスプレッドシートを取得
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetname);
// JSONデータをフラット化する関数
function flattenJson(data, prefix = '') {
let flatData = {};
for (let key in data) {
if (data.hasOwnProperty(key)) {
const newKey = prefix ? `${prefix}.${key}` : key; // prefixがあれば階層をつなげる
// 配列の場合、各要素をフラット化
if (Array.isArray(data[key])) {
data[key].forEach((item, index) => {
Object.assign(flatData, flattenJson(item, `${newKey}[${index}]`)); // インデックスをprefixにして再起呼び出し
});
}
// オブジェクトの場合は再帰的にフラット化
else if (typeof data[key] === 'object' && data[key] !== null) {
Object.assign(flatData, flattenJson(data[key], newKey)); // キーをprefixにして再起呼び出し
}
// 基本的な値(文字列、数値など)はそのまま格納
else {
flatData[newKey] = data[key];
}
}
}
return flatData;
}
// JSONをフラット化
const flatData = flattenJson(jsonData);
console.log(flatData); // コンソールで確認
// flatDataを2次元配列に変換
const data = Object.entries(flatData); // [["キー1", "値1"], ["キー2", "値2"], ...]
// スプレッドシートに書き込む
sheet.getRange(1, 1, data.length, 2).setValues(data);
Logger.log("JSONデータをスプレッドシートに書き込みました!");
}
使い方
writeJsonToSheet()にjsonオブジェクトと記入するシート名を渡します。
テキスト形式のjsonデータだとGASでは扱えないので、事前にJSON.parse()でオブジェクトに変換してから渡してください。
doPost()で受け取ったデータをシート1に記入する処理はこんな感じ。
function doPost(e) {
const jsonData = JSON.parse(e.postData.contents);
writeJsonToSheet(jsonData, "シート1");
}
解説
コメントを見ると分かると思うのですが、「JSONデータをフラット化する関数」と「連想配列をスプレッドシートに記入する」部分に分かれています。
ChatGPTさんソースを渡して質問すれば詳しく解説してもらえますが、私がprefixについて質問した時の回答を貼っておきます。
prefixは何に使っていますか?
prefix
は、再帰的に JSON をフラット化する際に キーの階層構造を保持しつつ、ユニークなキーを作成するため に使用しています。
例えば、元の JSON データでは階層が深くなると、以下のようなネストされた構造になっています:
jsonコードをコピーする{
"data": {
"object": {
"customer_address": {
"postal_code": "3191234",
"line1": "どっか",
"state": "茨城県"
}
}
}
}
このようなデータをフラット化するときに、prefix
を使ってキーを結合し、階層を表現した一意のキーを作成します。結果として以下のような形になります:
kotlinコードをコピーするdata.object.customer_address.postal_code : 3191234
data.object.customer_address.line1 : どっか
data.object.customer_address.state : 茨城県
prefix
の動作は以下の通りです:
動作の流れ
- 初期状態では
prefix
は空文字列''
です。 - 再帰呼び出しが行われる際、現在のキーを
prefix
に追加して渡します。- 例えば、
data
→data.object
→data.object.customer_address
のように階層を反映したキーが構築されます。
- 例えば、
- 配列の場合も同様に、
prefix
を活用してインデックス番号を含めた一意のキーを作成します。- 例:
items[0].description
,items[1].amount
- 例:
実際のコードでの例
javascriptコードをコピーするfunction flattenJson(data, prefix = '') {
let flatData = {};
for (let key in data) {
if (data.hasOwnProperty(key)) {
const newKey = prefix ? `${prefix}.${key}` : key; // prefixがあれば階層をつなげる
if (Array.isArray(data[key])) {
data[key].forEach((item, index) => {
Object.assign(flatData, flattenJson(item, `${newKey}[${index}]`)); // 配列の場合
});
} else if (typeof data[key] === 'object' && data[key] !== null) {
Object.assign(flatData, flattenJson(data[key], newKey)); // オブジェクトの場合
} else {
flatData[newKey] = data[key]; // それ以外の値
}
}
}
return flatData;
}
具体例での挙動
元の JSON:
jsonコードをコピーする{
"data": {
"object": {
"items": [
{ "description": "item1", "amount": 500 },
{ "description": "item2", "amount": 500 }
]
}
}
}
この JSON をフラット化した結果:
jsonコードをコピーする{
"data.object.items[0].description": "item1",
"data.object.items[0].amount": 500,
"data.object.items[1].description": "item2",
"data.object.items[1].amount": 500
}
prefix の重要性
- 階層構造を失わないようにする。
- キーの重複を防ぐ。
- スプレッドシートにデータを書き込む際に、どの階層のデータかがわかる。
これにより、階層の深い JSON を整理された形でスプレッドシートに書き込むことが可能になります。
ChatGPTさんありがとう!
最後に
なるべくシンプルになるようにChatGPTさんに訊きながら作ってみました。
連想配列のスプレッドシートへの記入部分も、Object.entries()を使うことでシンプルになったと思います。
良ければ使ってみてください。
では、良いGASライフを~
この記事が参考になったら下の「参考になった」ボタンをお願いします。
コメント