Help us understand the problem. What is going on with this article?

【Node.js】JSON文字列をCSVファイルとして吐き出す

要件

・DBに格納されているデータをCSVでダウンロードできるようにする
・データはユーザーが回答したアンケートの結果

使用したモジュール

・json2csv
https://www.npmjs.com/package/json2csv

開発

1. データの成形

今回は、ユーザーが回答したアンケート結果をCSVとして出力したいと思いますので、表示する項目をユーザー名メールアドレスアンケート設問回答結果とします。

データを成形する
    // DBから出力したいデータを取得する
    const data = await getData.getUserData(user_id);

    // データをJSON型に整える 
    const groupData = data.reduce((result, current) => {
      // user_idごとにデータをまとめる
      const element = result.find((p) => {
        return p.id === current.user_id;
      });
      // user_idが既にあればquestionとanswerのみを追加する
      if (element) {
        element.data.push({
          question: current.question,
          answer: current.answer
        });
      } else { // user_idが切り替わった時に新規の要素としてgroupDataに追加する
        result.push({
          id: current.user_id,
          name: current.user_name,
          email: current.user_email,
          data: [{
            question: current.question,
            answer: current.answer,
          }],
        });
      }
      return result;
    }, []);

DBから取得したデータをJSONに成形しました。reduce関数を使っているのは1クエリで適切な形でデータを取得できなかったためなので、必須ではありません。for文やmap関数を使ってきれいにしてください。
reduce関数でのデータをグループ化は以下を参考にさせて頂きました。


参考サイト
JavaScript オブジェクト配列をsqlのgroup byのように集計する


成形したデータは以下のようになりました。dataの個数は同じでなくても大丈夫です。

groupDataの中身
[
  {
    id: 267,
    name: "taro",
    email: "taro@example.com",
    data:[
      {
        question: "好きなプログラミング言語は?",
        answer: ["HTML", "CSS", "JavaScript"]
      },
      {
        question: "得意なプログラミング言語は?",
        answer: ["HTML", "CSS"]
      },
      {
        question: "苦手なプログラミング言語は?",
        answer: ["JavaScript"]
      }
    ]
  },
  {
    id: 269,
    name: "jiro",
    email: "jiro@example.com",
    data:[
      {
        question: "好きなプログラミング言語は?",
        answer: ["Go", "JavaScript"]
      },
      {
        question: "得意なプログラミング言語は?",
        answer: ["PHP", "Ruby"]
      },
      {
        question: "苦手なプログラミング言語は?",
        answer: ["Java"]
      }
    ]
  },
]

2. JSONをCSVに変換

続いてJSONに成形したデータをCSVに変換していきます。今回はjson2csvというモジュールを使用しました。他にもCSV系のモジュールはたくさんありましたので、自分にとって使いやすいものや仕様に沿っているものを選択すると良いかと思います。

get_csv.js
const {Parser, transforms: {unwind}} = require('json2csv');

function getCsv(data, fields, pathes, res) {
  const transforms = [unwind({
    paths: pathes,
    blankOut: true,
  })];
  const json2csvParser = new Parser({fields, transforms});
  const csv = data.length ? json2csvParser.parse(data) : '';
  res.setHeader('Content-disposition', 'attachment; filename=data.csv');
  res.setHeader('Content-Type', 'text/csv; charset=UTF-8');
  return res.send(csv);
}

module.exports = getCsv;

引数のdataは先程成形したデータが渡ってきます。fieldsにはdataの中の表示させたい項目を配列で渡します。今回の例ですと、以下のようになります。

fieldsの中身
const fields = ['name', 'email', 'data.question', 'data.answer'];

questionとanswerはdataの入れ子になっているのでドット繋ぎにします。

最後のpathesはdataの中でネストされている項目を配列で渡します。今回の例では以下のようになります。

pathesの中身
const pathes = ['data']

ここで、pathesの中にdata.answerを入れると、answerに格納されている配列が展開されて表示されるようになります。今回は、一つの設問に対して複数の回答を1行で表示させたかったのでdataのみにしました。
他にも色々オプションがありますので、詳しくは公式ドキュメントを参照してください。

3. CSVの出力

後は、CSVに変換したデータをPOSTなどのルーティングでres.sendしてあげることで、ブラウザからファイルをダウンロードすることができます。

CSV出力
const csv = getCsv(groupData, fields, pathes, res);
res.send(csv);

出力結果

以上です。

kum44
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした