Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8837

JavaScriptでJSONファイルを同ディレクトリ上に生成する

$
0
0

結論からいうとnodeを使って生成します。fsモジュールを使います。
「JavaScript JSONファイル 生成」とJavaScriptを使ったキーワードでググったところ某スクールの違う、そうじゃない、な記事やあまり関係のない記事が出てきてしまったため対抗馬としてJavaScriptを前面に押して記事にしました。(結局は他の記事と同じようにnodeを使いますが)

特に初学者は「ググっても出てこないじゃないか」、と困っているかと思います。記事の前提をクリアして手を動かしてみてください。

追記:もっと良い書き方あれば教えてもらえるとハッピーになります。

【この記事の前提】 nodeをインストールしよう

nodeとはサーバーサイドのJSです。ブラウザ以外のところでもJavaScriptを実行できるよ、という実行環境になります。
nodeとセットで語られるnpmは聞いたことがある人が多いと思いますがnodeで動く様々なモジュールを引っ張ってくるためのパッケージマネージャーです。

nodeをインストール

初心者は以下を参考に導入すると良いかと思います。
MacにNode.jsをインストール
windows10にNode.jsをインストールする

インストールの仕方はいくつかあり、今後JSフレームワークを使いたい人はanyenv経由でnodenvを導入してnodeのバージョン切り替えを楽にプロジェクトに応じてできるようにしておくと良いかと思います。
anyenv から入れた nodenv で Node.js を入れたときのメモ
MacにNode.jsをインストール(anyenv + nodenv編)
↑環境構築に少しは慣れている人向けです。自分はシェルをzsh環境へ変えるところから沼にハマってしまいしかもつまづいたところをメモに残してなかったのでどうやったのか思い出せない(バージョン切り替えできなくて残念でした)

node -v

でバージョンが表示されればOKです。

任意のディレクトリに今回のためのファイルを用意

% mkdir createObj //createObjフォルダを作る
% cd createObj //移動する
% touch create.js //jsファイルを作る

最小単位でfsモジュールを使ってJSONファイルを生成する

fsモジュールはnodeパッケージマネージャ(npmやyarn)からインストールしてこなくても最初からnodeの機能として備わっているためすぐに使うことができます。
create.jsのファイル編集します。

create.js
constfs=require('fs');consttestObj={test:'dammy',};constcreateFile=(pathName,source)=>{consttoJSON=JSON.stringify(source);fs.writeFile(pathName,toJSON,(err)=>{if(err)rej(err);if(!err){console.log('JSONファイルを生成しました');}});};createFile('newObj.json',testObj);

fs.writeFileでpathNameで指定したファイルを生成しています。
コマンドライン(ターミナル)で node create で実行すると newObj.json のファイルが同ディレクトリ上で生成されます。

% node create 
newObj.json
{"test":"dammy"}

JSONの中身を変えて再度実行するとファイルが上書きされます。

create.js
consttestObj={test:'second dammy',};

工夫1 ファイルのディレクトリ場所を変える

下の形で相対パスを指定すればOKです。

createFile('./任意のフォルダ/newObj.json', testObj);

工夫2 ファイルを上書き保存されないようにする

ディレクトリチェックを行えるfs.statSync()メソッドを用いてファイル重複を確認します。
同ディレクトリ上に既存ファイルがあった場合はreturnでメッセージを返します。

create.js
constfs=require('fs');consttestObj={test:'dammy',};constcreateFile=(pathName,source)=>{constisExist=dupliCheck(pathName);//booleanを挟むif(isExist)returnconsole.log('既存のパスが見つかりました');//エラーメッセを返すconsttoJSON=JSON.stringify(source);fs.writeFile(pathName,toJSON,(err)=>{if(err)throwerr;if(!err){console.log('JSONファイルを生成しました');}});};//新たに追加した関数constdupliCheck=(pathName)=>{try{fs.statSync(pathName);returntrue}catch(err){//パスが存在しない場合エラーを返すif(err.code==='ENOENT')returnfalse}};createFile('new.json',testObj);

工夫3 データ加工してJSONファイルを生成する

僕はこれがやりたくてfsモジュールを使いました。
エクセルからデータを加工すると手間がかかるので既存オブジェクトの値を元に計算した結果をオブジェクトに格納し生成したかったです。

ここでサンプルを用意しました。(なお、手っ取り早くデータが欲しいのでベストプラクティスみたいなところは意識してないんでそこらへんは許して欲しいンゴ。独学者のやり方なので良い方法あったら教えてください。)

サンプルデータの簡単な説明

例として食材データObjectに含む栄養データが1日あたりの摂取する推奨量に対してどのくらい割合を満たしているのかを算出したものをJSONデータとしてアウトプットします(dailyRationSample.jsonとして)

外部データを用意する

% mkdir seed
% touch seed/sampleStuff.js
% touch seed/sampleDaily.js

module.exports で外部データとして引っ張ってこれるようにしています。

sampleStuff.js
module.exports=[{id:1,Name:'アマランサス 玄穀 ',Protein:12.7,Iron:9.4,},{id:2,Name:'あわ 精白粒 ',Protein:11.2,Iron:4.8,},{id:3,Name:'あわ あわもち ',Protein:5.1,Iron:0.7,},];
sampleDaily.js
module.exports=[{name:'Protein',volume:60,},{name:'Iron',volume:7.5,},];

create.jsにデータを取り込んでオブジェクトを生成してファイルとしてアウトプットする

sampleStuff.jsの食材データの栄養素であるプロテイン(Protein)と鉄分(Iron)を sampleDaily.js の1日あたりの推奨量の大きさである volume とで割って割合を出してみましょう。

create.js
constfs=require('fs');conststuff=require('./seed/sampleStuff');//外部データを引っ張っているconstdaily=require('./seed/sampleDaily');//外部データを引っ張っている//新たに追加した関数constcreateObj=()=>{constobjArray=[],directArr=['id','Name'],divisionArr=['Protein','Iron'];stuff.map(stuffObj=>{constsingleObj={};directArr.map(keyName=>{singleObj[keyName]=stuffObj[keyName];});divisionArr.map(keyName=>{constdailyObj=daily.find(item=>keyName===item.name);const{volume:denomi}=dailyObj,//分割代入したvolumeの名前をdenomi(分母)にしているmolecule=stuffObj[keyName],//molecleは分子ratio=Math.round(molecule/denomi*1000)/1000;singleObj[keyName]=ratio;});objArray.push(singleObj);});returnobjArray;}constcreateFile=(pathName)=>{constisExist=dupliCheck(pathName);if(isExist)returnconsole.log('既存のパスが見つかりました');consttargetObj=createObj();consttoJSON=JSON.stringify(targetObj,null,4);//行数が多いのでオプション指定して改行しておくfs.writeFile(pathName,toJSON,(err)=>{if(err)throwerr;if(!err){console.log('JSONファイルを生成しました');}});};constdupliCheck=(pathName)=>{try{fs.statSync(pathName);returntrue}catch(err){if(err.code==='ENOENT')returnfalse}};createFile('dailyRatioSample.json');

上記を実行するとdailyRatioSample.jsonが生成されます。

dailyRatioSample.json
[{"id":1,"Name":"アマランサス 玄穀 ","Protein":0.212,"Iron":1.253},{"id":2,"Name":"あわ 精白粒 ","Protein":0.187,"Iron":0.64},{"id":3,"Name":"あわ あわもち ","Protein":0.085,"Iron":0.093}]

蛇足(記事更新)

JSON整形は別記事で説明しようと思いましたがやっぱりここで説明
下記のようにJSON.stringfy(オブジェクト, 置換オプション, 字下げ数)を指定して整形ことができます。

const toJSON = JSON.stringify(targetObj, null, 4);
つまり
const toJSON = JSON.stringify(オブジェクト, 置換オプション, 字下げ数);

「置換オプションってなんだよ」というところですが僕も使ったことがありません。(使うタイミングにまだ巡り合っていない)
JSON.stringify() - MDN Web Docs - Mozillaのサイトで構文を確認すると

JSON.stringify(value[, replacer[, space]])

となっています。また下の記事の引用では下記のような説明となっています。

"もし関数である場合、文字列化の間に出会った値とプロパティを変換します。もし配列である場合は、最終的な文字列のオブジェクトに含まれるプロパティの集合を指定します。" 引用:JSON.stringifyを改めて調べる。

JSONに含まれる関数と配列を置き換えできるようです。


Viewing all articles
Browse latest Browse all 8837

Trending Articles