🦋

JavaScriptで配列形式のJSONをCSVに変換してダウンロードする方法

2023/12/29に公開

こんにちは、AIQ株式会社のフロントエンドエンジニアのまさぴょんです!
今回は、JavaScriptで配列形式のJSONをCSVに変換してダウンロードする方法について、解説します。

配列形式のJSONをCSVに変換してダウンロードする方法 Part1

最初に作成した、配列形式のJSONをCSVに変換してダウンロードする方法は次のとおりです。

処理フロー・要点まとめ
  1. ObjectKeyheaderとして取り出して、結合する
  2. Objectvalueを取り出して、結合する
  3. CSV文字列を返却する
  4. Blob Object(Type.CSV)を作成する
  5. Blob Object(Type.CSV)のURLを作成する
  6. aリンクを作成する
  7. hrefdownload属性を追加して、クリックする
  8. aリンクを削除する
const groupList = [
  { id: 1, participant: "ロボたま", affiliation: "エンジニア" },
  { id: 2, participant: "まりたま", affiliation: "エンジニア" },
  { id: 3, participant: "白桃", affiliation: "営業部" },
  { id: 4, participant: "ももちゃん", affiliation: "営業部" },
  { id: 5, participant: "まさぴょん", affiliation: "営業部" },
  { id: 6, participant: "まりぴょん", affiliation: "デザイナー" },
  { id: 7, participant: "ハム太郎", affiliation: "エンジニア" },
  { id: 8, participant: "ロボ太郎", affiliation: "デザイナー" },
  { id: 9, participant: "まり太郎", affiliation: "デザイナー" },
  { id: 10, participant: "ぷる玉", affiliation: "人事部" },
  { id: 11, participant: "ぷるぷる玉", affiliation: "人事部" },
  { id: 12, participant: "ロボ玉試作1号機", affiliation: "エンジニア" },
  { id: 13, participant: "ロボ玉試作2号機", affiliation: "デザイナー" },
  { id: 14, participant: "ロボ玉試作1号機", affiliation: "ロボ玉開発部" },
];

/** Object の配列を受け取り CSV形式の文字列に変換する Func */
const convertToCSV = (objArray) => {
  const array = typeof objArray !== "object" ? JSON.parse(objArray) : objArray;

  /** 1. Objectの Key を headerとして取り出す */
  let str =
    `${Object.keys(array[0])
      .map((value) => `"${value}"`)
      .join(",")}` + "\r\n";

  // 2. 各オブジェクトの値をCSVの行として追加する
  return array.reduce((str, next) => {
    str +=
      `${Object.values(next)
        .map((value) => `"${value}"`)
        .join(",")}` + "\r\n";
    return str;
  }, str);
};

/** Download・処理 */
const downloadCSV = (data, name) => {
  /** Blob Object を作成する Type. CSV */
  const blob = new Blob([data], { type: "text/csv" });
  console.log("blob", blob);
  const url = window.URL.createObjectURL(blob);
  console.log("url", url);
  const a = document.createElement("a");
  a.setAttribute("href", url);
  a.setAttribute("download", `${name}.csv`);
  a.click();
  a.remove();
};

/** CSVデータを作成 */
const csvData = convertToCSV(groupList);
console.log(csvData);

// CSV・Download
downloadCSV(csvData, "robotama");

https://dev.to/frehner/the-order-of-js-object-keys-458d

このScriptをconsoleで実行してもらうと、次のようなCSVファイルが作成されます。

配列形式のJSONをCSVに変換してダウンロードする方法 Part2

最初に作成した方法だと、Object.keys()によって、順序の保証がない場合があります。

そこで、まったく同じことをしようとしていた記事を見つけたので、こちらを参考・引用させてもらい、次のような配列形式のJSONをCSVに変換してダウンロードする方法も作成しました。

処理フロー・要点まとめ
  1. ObjectからMapの生成(Mapkeyの順序が保証されている)
  2. Mapから配列を作成して、CSVのHeaderList(KeyList)を作成する
  3. header行を結合する
  4. Objectvalueを結合して、コンテンツ部分を作成する
  5. headerとコンテンツ部分を結合して、CSVフォーマットの文字列を作成する
  6. Blob Object(Type.CSV)を作成する
  7. Blob Object(Type.CSV)のURLを作成する
  8. aリンクを作成する
  9. hrefdownload属性を追加して、クリックする
  10. aリンクを削除する
const groupList = [
  { id: 1, participant: "ロボたま", affiliation: "エンジニア" },
  { id: 2, participant: "まりたま", affiliation: "エンジニア" },
  { id: 3, participant: "白桃", affiliation: "営業部" },
  { id: 4, participant: "ももちゃん", affiliation: "営業部" },
  { id: 5, participant: "まさぴょん", affiliation: "営業部" },
  { id: 6, participant: "まりぴょん", affiliation: "デザイナー" },
  { id: 7, participant: "ハム太郎", affiliation: "エンジニア" },
  { id: 8, participant: "ロボ太郎", affiliation: "デザイナー" },
  { id: 9, participant: "まり太郎", affiliation: "デザイナー" },
  { id: 10, participant: "ぷる玉", affiliation: "人事部" },
  { id: 11, participant: "ぷるぷる玉", affiliation: "人事部" },
  { id: 12, participant: "ロボ玉試作1号機", affiliation: "エンジニア" },
  { id: 13, participant: "ロボ玉試作2号機", affiliation: "デザイナー" },
  { id: 14, participant: "ロボ玉試作1号機", affiliation: "ロボ玉開発部" },
];

/** Objectのリストから、CSVを作成する */
const convertToCSV = (data, headerOrder) => {
  /** headerOrderを入れているのは、JavaScriptの場合Object.keys()だと順番が必ずしも守られないからです。 */
  const headerString = headerOrder.join(",");
  const replacer = (_, value) => value ?? "";
  const rowItems = data.map((row) =>
    headerOrder
      .map((fieldName) => JSON.stringify(row[fieldName], replacer))
      .join(",")
  );

  /** headerとコンテンツ部分を結合して、CSVフォーマットの文字列を作成する */
  const csv = [headerString, ...rowItems].join("\r\n");
  return csv;
};

/** Download・処理 */
const downloadCSV = (data, name) => {
  /** Blob Object を作成する Type. CSV */
  const blob = new Blob([data], { type: "text/csv" });
  const url = window.URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.setAttribute("href", url);
  a.setAttribute("download", `${name}.csv`);
  a.click();
  a.remove();
};

/** 1つの行・データ */
const csvRow = groupList[0];

/** Object から、Map の生成 => Map は、key の順序が保証されている */
const csvRowMap = new Map(Object.entries(csvRow));

// Mapから配列を作成して、CSV の HeaderList(KeyList)を作成する
const csvHeader = Array.from(csvRowMap).map((keyValList) => keyValList[0]);
console.log("csvHeader", csvHeader);

// CSVデータを作成する
const csvData = convertToCSV(groupList, csvHeader);
console.log(csvData);

// CSV・Download
downloadCSV(csvData, "robotama2");

このScriptをconsoleで実行してもらうと、次のようなCSVファイルが作成されます。

【おまけ】 配列形式のJSONと配列型のリストとの相互変換

配列形式のJSONから配列型のリストに変換する

const groupList = [
  { id: 1, participant: "ロボたま", affiliation: "エンジニア" },
  { id: 2, participant: "まりたま", affiliation: "エンジニア" },
  { id: 3, participant: "白桃", affiliation: "営業部" },
  { id: 4, participant: "ももちゃん", affiliation: "営業部" },
  { id: 5, participant: "まさぴょん", affiliation: "営業部" },
  { id: 6, participant: "まりぴょん", affiliation: "デザイナー" },
  { id: 7, participant: "ハム太郎", affiliation: "エンジニア" },
  { id: 8, participant: "ロボ太郎", affiliation: "デザイナー" },
  { id: 9, participant: "まり太郎", affiliation: "デザイナー" },
  { id: 10, participant: "ぷる玉", affiliation: "人事部" },
  { id: 11, participant: "ぷるぷる玉", affiliation: "人事部" },
  { id: 12, participant: "ロボ玉試作1号機", affiliation: "エンジニア" },
  { id: 13, participant: "ロボ玉試作2号機", affiliation: "デザイナー" },
  { id: 14, participant: "ロボ玉試作1号機", affiliation: "ロボ玉開発部" },
];

/** 1つの行・データ */
const csvRow = groupList[0];
/** Object から、Map の生成 => Map は、key の順序が保証されている */
const csvRowMap = new Map(Object.entries(csvRow));

const csvHeader = [];

// Mapから配列を作成して、CSV の HeaderList(KeyList)を作成する
Array.from(csvRowMap).forEach((keyValList) => {
  csvHeader.push(keyValList[0]);
});

const listCSV = [csvHeader];
groupList.forEach((row) => {
  listCSV.push([row.id, row.participant, row.affiliation]);
});
console.log(listCSV);
/** 実行結果 */
// [
//   ["id", "participant", "affiliation"],
//   [1, "ロボたま", "エンジニア"],
//   [2, "まりたま", "エンジニア"],
//   [3, "白桃", "営業部"],
//   [4, "ももちゃん", "営業部"],
//   [5, "まさぴょん", "営業部"],
//   [6, "まりぴょん", "デザイナー"],
//   [7, "ハム太郎", "エンジニア"],
//   [8, "ロボ太郎", "デザイナー"],
//   [9, "まり太郎", "デザイナー"],
//   [10, "ぷる玉", "人事部"],
//   [11, "ぷるぷる玉", "人事部"],
//   [12, "ロボ玉試作1号機", "エンジニア"],
//   [13, "ロボ玉試作2号機", "デザイナー"],
//   [14, "ロボ玉試作1号機", "ロボ玉開発部"],
// ];

配列型のリストから配列形式のJSONに変換する

const listCSV = [
  ["id", "participant", "affiliation"],
  [1, "ロボたま", "エンジニア"],
  [2, "まりたま", "エンジニア"],
  [3, "白桃", "営業部"],
  [4, "ももちゃん", "営業部"],
  [5, "まさぴょん", "営業部"],
  [6, "まりぴょん", "デザイナー"],
  [7, "ハム太郎", "エンジニア"],
  [8, "ロボ太郎", "デザイナー"],
  [9, "まり太郎", "デザイナー"],
  [10, "ぷる玉", "人事部"],
  [11, "ぷるぷる玉", "人事部"],
  [12, "ロボ玉試作1号機", "エンジニア"],
  [13, "ロボ玉試作2号機", "デザイナー"],
  [14, "ロボ玉試作1号機", "ロボ玉開発部"],
];

const headers = listCSV[0];
const newList = listCSV.slice(1).map((row) => {
  let obj = {};
  row.forEach((value, index) => {
    obj[headers[index]] = value;
  });
  return obj;
});

console.log(newList);
/** 実行結果 */
// [
//   { id: 1, participant: "ロボたま", affiliation: "エンジニア" },
//   { id: 2, participant: "まりたま", affiliation: "エンジニア" },
//   { id: 3, participant: "白桃", affiliation: "営業部" },
//   { id: 4, participant: "ももちゃん", affiliation: "営業部" },
//   { id: 5, participant: "まさぴょん", affiliation: "営業部" },
//   { id: 6, participant: "まりぴょん", affiliation: "デザイナー" },
//   { id: 7, participant: "ハム太郎", affiliation: "エンジニア" },
//   { id: 8, participant: "ロボ太郎", affiliation: "デザイナー" },
//   { id: 9, participant: "まり太郎", affiliation: "デザイナー" },
//   { id: 10, participant: "ぷる玉", affiliation: "人事部" },
//   { id: 11, participant: "ぷるぷる玉", affiliation: "人事部" },
//   { id: 12, participant: "ロボ玉試作1号機", affiliation: "エンジニア" },
//   { id: 13, participant: "ロボ玉試作2号機", affiliation: "デザイナー" },
//   { id: 14, participant: "ロボ玉試作1号機", affiliation: "ロボ玉開発部" },
// ];

まとめ

配列形式のJSONをCSVに変換してダウンロードする処理は、それなりに使用する処理になると思うので、誰かのお役に立てれば、幸いです。

個人で、Blogもやっています、よかったら見てみてください。

https://masanyon.com/

注意事項

この記事は、AIQ 株式会社の社員による個人の見解であり、所属する組織の公式見解ではありません。

求む、冒険者!

AIQ株式会社では、一緒に働いてくれるエンジニアを絶賛、募集しております🐱🐹✨

詳しくは、Wantedly (https://www.wantedly.com/companies/aiqlab)を見てみてください。

参考・引用

https://zenn.dev/yui/articles/32b02c23e70dbc

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/keys

https://dev.to/frehner/the-order-of-js-object-keys-458d

https://javascript.plainenglish.io/does-javascript-guarantee-object-property-order-36c3630e320b

AIQ Tech Blog (有志)

Discussion