表示調整
閉じる
挿絵表示切替ボタン
▼配色
▼行間
▼文字サイズ
▼メニューバー
×閉じる

ブックマークに追加しました

設定
0/400
設定を保存しました
エラーが発生しました
※文字以内
ブックマークを解除しました。

エラーが発生しました。

エラーの原因がわからない場合はヘルプセンターをご確認ください。

205/210

JavaScriptで2つのJSONを比較して同じものかを調べるコードを書いてみた

前の投稿でTypescript版について書きましたが、javasciptでもテストしました。

名前は"fnjs"としています。


なお、Typescriptでjavascriptファイルをインポートするため、以下のように記述しました。


//test javascript

const {fnjs} =require('src/assets/mycode/test.js')


十分わかってはいないのですが、Typescriptでjavascriptファイルを読み込むには

・型定義ファイルを用意する

・モジュールをrequireで読み込む

の2つの方法があり、今回は簡便な(と思われる)requireで読み込みました。


以下は、javascript版のソースコードです。(型定義の部分を外しただけ)


----------------------------------------------------------------------

export function fnjs(obj1, obj2, strict=true){ //strictはオプション引数。falseならば文字列"1"と数値1は同じものとして扱う。

let arrAccessKey=[];

const typeObj1=typeof(obj1)

const typeObj2=typeof(obj2)

const nullObj1=(obj1==null)

const nullObj2=(obj2==null)

const arrayObj1=Array.isArray(obj1)

const arrayObj2=Array.isArray(obj2)

let rtnObj={

"result":true, "type of obj1":typeObj1, "type of obj2":typeObj2,

"obj1 is null":nullObj1, "obj2 is null":nullObj2,

"obj1 is Array":arrayObj1, "obj2 is Array":arrayObj2,

"strict":strict,

"desc":"", "AccessKey":arrAccessKey,"loop counter":0

};


try {

const isTest=false;

let cntloop=0;


//初期チェック

//単純比較(ともにnullなども含む)

if(strict){

if(obj1===obj2){

rtnObj["result"]=true;

rtnObj["desc"]='obj1===obj2';

return rtnObj;

}

}else{

if(obj1==obj2){

rtnObj["result"]=true;

rtnObj["desc"]='obj1==obj2';

return rtnObj;

}

}


switch (typeObj1) {

case "string":

case "number":

case "boolean":

case "undefined":

case "bigint":

case "symbol": //https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Symbol

case "function":

if(typeObj1==typeObj2){

rtnObj["result"]=false;

rtnObj["desc"]="obj1 and obj2 are different values";

return rtnObj;

}else{

rtnObj["result"]=false;

rtnObj["desc"]="obj1 and obj2 are different types";

return rtnObj;

}


case "object":

//nullで等しいケースは除外済みだが片方のみnullはありえる

if(nullObj1||nullObj2){

rtnObj["result"]=false; //等しいケースは除外済み

rtnObj["desc"]="One is null, the other is not";

return rtnObj;

}

//Array?

if(arrayObj1!=arrayObj2){

rtnObj["result"]=false; //等しいケースは除外済み

rtnObj["desc"]="One is an array, the other is an Object";

return rtnObj;

}

//key

if(Object.keys(obj1).length!=Object.keys(obj2).length){

rtnObj["result"]=false;

rtnObj["desc"]="Different number of keys";

return rtnObj;

}

if(Object.keys(obj1).length==0){ //少なくとも一つは要素を持つ

rtnObj["result"]=true;

rtnObj["desc"]="Note: This object has no keys";

return rtnObj;

}


break;


default: //予期せぬエラー

rtnObj["result"]=false;

rtnObj["desc"]="switch (typeObj1) {";

return rtnObj;

}


//各階層には複数あるいは一つのBlockが存在する。チェックするのは一度に一つのみ

let key1=Object.keys(obj1);

let chkBlockIndex=0; //Keyのないケースは初期チェックで除外済み(等しい、等しくないにかかわらず)

let BlockLength=key1.length; //隣接のBlockの数(経路が変われば異なる算出が必要)

let arrCheckInfo=[];

let arrTemp=[obj1, obj2, chkBlockIndex, BlockLength, key1];

//obj1, obj2 : 比較すべきobjあるいはArrayあるいは値

//chkBlockIndex, BlockLength : 検査するブロック内インデックスとブロックの保持する項目の数

//key1 : ブロック各項目にアクセスするキー配列(ex. obj1[key1[chkBlockIndex]])

//上記項目を階層ごとに作成してarrCheckInfoにpush

arrCheckInfo.push(arrTemp);


//初回のキーの存在チェック(obj2)

if(obj2[arrCheckInfo[0][4][arrCheckInfo[0][2]]]==undefined && obj2[arrCheckInfo[0][4][arrCheckInfo[0][2]]]!=null){

rtnObj["result"]=false;

rtnObj["desc"]="obj2 does not have key "+arrCheckInfo[0][4][arrCheckInfo[0][2]];

arrAccessKey=[];

rtnObj["AccessKey"]=arrAccessKey;

return rtnObj;

}


let lastindex=arrCheckInfo.length-1;

//Loop

let flg1stLoop=true; //最初のループ

let flgLoopNext=true; //falseになるまでLoop

do {

lastindex=arrCheckInfo.length-1;

rtnObj["loop counter"]++;


//for test

if(isTest){

cntloop++;

if(cntloop>5){

rtnObj["result"]=false;

rtnObj["desc"]="for test : cntloop>5";

return rtnObj;

}

}


if(arrCheckInfo[lastindex][2]>arrCheckInfo[lastindex][3]-1 && !flg1stLoop){

//初回のループで無く、このブロックの要素の最後がチェック済み

if(lastindex<=0){ //flg1stLoop=falseなので初回ではない(初回ブロック数1はあり得る)

//最上位の階層ならばブロックは一つのみ、ゆえにすべてのチェックが終了

rtnObj["result"]=true;

rtnObj["desc"]="Check completed!";

flgLoopNext=false; //チェック終了(obj1とobj2は等しい)

}else{

//同じ階層に次のブロックがなく最上位の階層でなければ、現在の階層をpopして一つ階層を上がり次のブロックの検査

arrCheckInfo.pop();

arrCheckInfo[lastindex-1][2]++; //次のループへ

}

}else{

//このブロックの比較すべき要素をチェック

let elmtemp1 //比較すべき要素1

let elmtemp2 //比較すべき要素2


arrCheckInfo.map((Element,index)=>{

if(index==0){

elmtemp1=obj1[Element[4][Element[2]]]; //インデックス番目(Element[2])のKey(Element[4])

elmtemp2=obj2[Element[4][Element[2]]];

}else{

elmtemp1=elmtemp1[Element[4][Element[2]]]; //インデックス番目(Element[2])のKey(Element[4])

elmtemp2=elmtemp2[Element[4][Element[2]]];

}

})


//undefined obj1にあるキーがobj2に存在しない

if(elmtemp2==undefined && elmtemp2!=null){

rtnObj["result"]=false;

rtnObj["desc"]="obj2 does not have key "+arrCheckInfo[lastindex][4][arrCheckInfo[lastindex][2]];

arrAccessKey=[];

arrCheckInfo.map((el)=>{arrAccessKey.push(el[4][el[2]])});

rtnObj["AccessKey"]=arrAccessKey;

return rtnObj;

}


const typetemp1=typeof(elmtemp1);

//要素チェック

switch (typetemp1) {

case "string":

case "number":

case "boolean":

case "undefined":

if(strict){

if(elmtemp1!==elmtemp2){

rtnObj["result"]=false;

rtnObj["desc"]="property1!==property2";

arrAccessKey=[];

arrCheckInfo.map((el)=>{arrAccessKey.push(el[4][el[2]])});

rtnObj["AccessKey"]=arrAccessKey;

return rtnObj;

}

}else{

if(elmtemp1!=elmtemp2){

rtnObj["result"]=false;

rtnObj["desc"]="property1!=property2";

arrAccessKey=[];

arrCheckInfo.map((el)=>{arrAccessKey.push(el[4][el[2]])});

rtnObj["AccessKey"]=arrAccessKey;

return rtnObj;

}

}

//次の要素の検査へ

arrCheckInfo[lastindex][2]++; //次のループへ

break;


case "bigint":

case "symbol": //https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Symbol

case "function":

//この3種類はJSONの仕様上ありえない

rtnObj["result"]=false;

rtnObj["desc"]="unexpected error : typeof(elmtemp1) = "+elmtemp1

arrAccessKey=[];

arrCheckInfo.map((el)=>{arrAccessKey.push(el[4][el[2]])});

rtnObj["AccessKey"]=arrAccessKey;

return rtnObj;


case "object":

//null

if((elmtemp1==null)!=(elmtemp2==null)){

rtnObj["result"]=false;

rtnObj["desc"]="One is null, the other is not";

arrAccessKey=[];

arrCheckInfo.map((el)=>{arrAccessKey.push(el[4][el[2]])});

rtnObj["AccessKey"]=arrAccessKey;

return rtnObj;

}else{

if(elmtemp1==null){ //どちらもnull

//次の要素の検査へ

arrCheckInfo[lastindex][2]++; //次のループへ

break;

}

}

//Array

if(Array.isArray(elmtemp1)!=Array.isArray(elmtemp2)){

rtnObj["result"]=false;

rtnObj["desc"]="One is Array, the other is not";

arrAccessKey=[];

arrCheckInfo.map((el)=>{arrAccessKey.push(el[4][el[2]])});

rtnObj["AccessKey"]=arrAccessKey;

return rtnObj;

}

//Key

const keyTemp1=Object.keys(elmtemp1);

const keyLength1=keyTemp1.length;

if(keyLength1!=Object.keys(elmtemp2).length){

rtnObj["result"]=false;

rtnObj["desc"]="The number of keys in obj1 is different from the number of keys in obj2";

arrAccessKey=[];

arrCheckInfo.map((el)=>{arrAccessKey.push(el[4][el[2]])});

rtnObj["AccessKey"]=arrAccessKey;

return rtnObj;

}

//arrCheckInfoに追加して次のループへ

const arrTemp=[

elmtemp1,

elmtemp2,

0,

keyLength1,

keyTemp1

];

arrCheckInfo.push(arrTemp);

break;


default: //予期せぬエラー

rtnObj["result"]=false;

rtnObj["desc"]="unexpected error"

arrAccessKey=[];

arrCheckInfo.map((el)=>{arrAccessKey.push(el[4][el[2]])});

rtnObj["AccessKey"]=arrAccessKey;

return rtnObj;

}

}

if(flg1stLoop){flg1stLoop=false};


} while (flgLoopNext);


return rtnObj;


} catch (error) {

rtnObj["result"]=false;

rtnObj["desc"]="try catch error : "+String(error)

return rtnObj;

}

}


評価をするにはログインしてください。
ブックマークに追加
ブックマーク機能を使うにはログインしてください。
― 新着の感想 ―
このエピソードに感想はまだ書かれていません。
感想一覧
+注意+

特に記載なき場合、掲載されている作品はすべてフィクションであり実在の人物・団体等とは一切関係ありません。
特に記載なき場合、掲載されている作品の著作権は作者にあります(一部作品除く)。
作者以外の方による作品の引用を超える無断転載は禁止しており、行った場合、著作権法の違反となります。

この作品はリンクフリーです。ご自由にリンク(紹介)してください。
この作品はスマートフォン対応です。スマートフォンかパソコンかを自動で判別し、適切なページを表示します。

↑ページトップへ