つくってみよう - FireFox拡張機能でブックマークを一覧表示する（６）ソースコードを読む - JSON情報の取得について

# つくってみよう - FireFox拡張機能でブックマークを一覧表示する 記事一覧
[つくってみよう - FireFox拡張機能でブックマークを一覧表示する（１）公式サンプルを体験する](https://qiita.com/madaaamj/items/5bf2ed67a2f68b0aa243)
[つくってみよう - FireFox拡張機能でブックマークを一覧表示する（２）動作を確認する](https://qiita.com/madaaamj/items/3e33b058ad2f13167084)
[つくってみよう - FireFox拡張機能でブックマークを一覧表示する（３）ソースコードを読む - 構成について]
(https://qiita.com/madaaamj/items/bef7102722da2f249515)
[つくってみよう - FireFox拡張機能でブックマークを一覧表示する（４）ソースコードを読む - 画面について]
(https://qiita.com/madaaamj/items/27dd820d10fd20c51dee)
[つくってみよう - FireFox拡張機能でブックマークを一覧表示する（５）ソースコードを読む - 処理の概要について]
(https://qiita.com/madaaamj/items/af88405b30820b19a114)
[つくってみよう - FireFox拡張機能でブックマークを一覧表示する（６）ソースコードを読む - JSON情報の取得について]
(https://qiita.com/madaaamj/items/d9e7b1c296221218d46a)
[つくってみよう - FireFox拡張機能でブックマークを一覧表示する（７）ソースコードを読む - 表示について①]
(https://qiita.com/madaaamj/items/68888b5d0fdb8f2af84f)
[つくってみよう - FireFox拡張機能でブックマークを一覧表示する（８）ソースコードを読む - 表示について②]
(https://qiita.com/madaaamj/items/a7e3f764f8177139bf7d)

# ソースコードを読む
「FireFox拡張機能でブックマークを一覧表示する」機能をつくっていきましょう。
今回はJSON情報の取得の処理を見ていきます。

# ブックマークファイルを読み込み配列に入れる
選択されたブックマークファイルのデータが保持されている変数`lines`を[JSON.parse()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse)でパースしてオブジェクト`jsonObj`に保持します。

そして`makeTagdic()`で`jsonObj`を元に変数`dicTags`にキー／値の組み合わせで連想配列風配列を生成します。

```javascript:bmlist.js（readFile一部）
// 1.ブックマークファイルを選択して読み込み一覧表を生成する。
function readFile() { 
・・・
    // ファイル読み込み時：ブックマークファイル（.json）を読み込む
    reader.onload = function(e) {
        let lines = e.target.result;
        const jsonObj = JSON.parse(lines);

        // JSONから辞書（連想配列）を作る
        let dicTags = [];
        try {
            makeTagdic(jsonObj, dicTags);    
        }
        catch (e) {
            alert("Error : " + e.message);
            return false;
        }
・・・
```

# ブックマークファイル（.json）の情報を保持する連想配列（dicTags）を生成する（makeTagdic）
makeTagdic関数では直前でパースした`jsonObj`を元に変数`dicTags`にキー／値の組み合わせで連想配列風配列を生成します。

```javascript:bmlist.js（makeTagdic）
// 2.readFileから呼び出される。ブックマークファイル（.json）の情報を保持する連想配列（dicTags）を生成する。
function makeTagdic(jsonObj, dicTags) {
    // タグ辞書を作る
    let bookmarks = jsonObj['children']; // ルートの子供
    for (let i = 0; i < bookmarks.length; i++) {
        let folders = bookmarks[i].children;
        if (folders) {
            for (let j = 0; j < folders.length; j++) {
                let arrFolders = [];
                switchByTypecode(folders[j], dicTags, arrFolders);
            }
        }
    }

    // 取得したタグ辞書をソート
    dicTags.sort(function(a, b) {
        // フォルダーをタグより上に表示する
        let flagA = a.folder;
        let flagB = b.folder;
        if (flagA < flagB) return 1; // 0より大きい場合、bをaより小さいインデックスにソート
        if (flagA > flagB) return -1; // 0未満の場合、aをbより小さいインデックスにソート

        // タイトル（フォルダー名・タグ名）の昇順にソートする
        let nameA = a.name;
        let nameB = b.name;
        if (nameA < nameB) return -1;
        if (nameA > nameB) return 1;

        // URLの昇順にソートする
        let urlA = a.url.toUpperCase(); // 大文字と小文字を無視する
        let urlB = b.url.toUpperCase(); // 大文字と小文字を無視する
        if (urlA < urlB) return -1;
        if (urlA > urlB) return 1;

        return 0; // 0を返した場合、aとbは互いに変更せず、他のすべての要素に対してソート
    });
}

```

まずJSONファイルの構造を見ていきましょう。
GitHubに[読みやすく整形したJSONファイル](https://github.com/madaaamj/webextensions/blob/main/FireFox/ex_bm_search/formatted_bookmarks-sample.json)を置きましたのでそちらを参照しながら解説していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277081/223bf6d8-53c0-8b1d-56f6-1785bfcac5a5.png)
最初（ルート）にある'children'タグの内容を取得します。
'children'には`"title": "ブックマークメニュー",` `"title": "ブックマークツールバー",` `"title": "他のブックマーク",` `"title": "モバイルのブックマーク",`の４つのブロックがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277081/680beae4-46a3-6a19-cc96-c597cd3857c6.png)
それぞれのブロックの中に'children'があり、下層へ向かって辿っていくと`"typeCode": 1,`を持つブロックにブックマーク情報があります。下の画像ではブックマークで"mecab"フォルダーにあるタグが`"tags": "MeCab,リファレンス,自然言語処理",`、タイトルが`"title": "MeCab: Yet Another Japanese Dependency Structure Analyzer",`、URLが`"uri": "http://taku910.github.io/mecab/format.html"`についてのブックマークの情報が保持されていることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277081/3209ba36-b3ea-3130-dfdc-99f93d273b57.png)
このJSONの構造を利用して上のようなブックマーク情報を`dicTags`に保持していきます。

今回は`switchByTypecode()`で`typeCode`を見て2の場合は再帰的に下層を辿っていく関数で処理しています。`typeCode`が1の場合はブックマーク情報なのでこのブロックの情報を`makeDictionary()`で`dicTags`にセットします。

```javascript:bmlist.js（switchByTypecode）
// 3.makeTagdicから呼び出される。JSONのURL要素まで下りブックマークの情報を取得する。
function switchByTypecode(folderObj, dicTags, arrFolders) {
    switch (folderObj.typeCode) {
        case 1: // bookmark "text/x-moz-place"
            if (!folderObj.uri.includes("place:")) { // "最近付けたタグ"と"よく見るページ"は含めない
                makeDictionary(folderObj, dicTags, arrFolders);
                arrFolders = [];
            }
            arrFolders = [];
            break;
        case 2: // folder "text/x-moz-place-container"
            arrFolders.push(folderObj.title);
            let folders = folderObj.children;
            if (folders) {
                for (let i = 0; i < folders.length; i++) {
                    switchByTypecode(folders[i], dicTags, arrFolders); // 再起呼び出し
                }
            }
            arrFolders.pop();
            break;
        case 3: // "text/x-moz-place-separator"
            break;
        default:
            break;
    }
}
```

`makeDictionary()`では、タグがセットされている場合は`{name:item, title:jsonObj.title, url:jsonObj.uri, iconurl:jsonObj.iconuri, folder:0}`のようにタグ名、タイトル、URL、アイコンURL（アイコンを表示するためにセット、ブックマークが多い場合アクセスが発生しすぎるので今回はこの機能は未使用にしてあります）、フォルダーフラグをセットします。

`switchByTypecode()`で`typeCode`が2の場合はフォルダーなので情報がフォルダー配列にセットしてあります。
この内容で`{name:"F-" + item, title:jsonObj.title, url:jsonObj.uri, iconurl:jsonObj.iconuri, folder:1}`のようにフォルダー名（F-付き）、タイトル、URL、アイコンURL、フォルダーフラグをセットします。

```javascript:bmlist.js（makeDictionary）
// 4.switchByTypecodeから呼び出される。ブックマークファイル（.json）の情報を保持する連想配列（dicTags）を生成する。
function makeDictionary(jsonObj, dicTags, arrFolders) {
    g_bookmark_num = g_bookmark_num + 1;

    let strTags = jsonObj.tags;
    if (strTags) {
        let arrTags = strTags.split(",");
        arrTags.forEach(function(item){
            dicTags.push({name:item, title:jsonObj.title, url:jsonObj.uri, iconurl:jsonObj.iconuri, folder:0});
        })
    }

    // folder tag array があったらタグリストに追加 dicTagsにfolder:0/1を追加する
    if (arrFolders.length > 0) {
        arrFolders.forEach(function(item){
            dicTags.push({name:"F-" + item, title:jsonObj.title, url:jsonObj.uri, iconurl:jsonObj.iconuri, folder:1});
        })
    }
}
```

すべてのブックマーク情報を`dicTags`に保持したら表示用に並び順をソートします。
`makeDictionary()`でセットしたフォルダーフラグでフォルダーを上にタグを下にソートします。
次にタイトル（フォルダー名・タグ名）の昇順にソート、最後にURLの昇順にソートします。

```javascript:bmlist.js（makeTagdic一部）
    // 取得したタグ辞書をソート
    dicTags.sort(function(a, b) {
        // フォルダーをタグより上に表示する
        let flagA = a.folder;
        let flagB = b.folder;
        if (flagA < flagB) return 1; // 0より大きい場合、bをaより小さいインデックスにソート
        if (flagA > flagB) return -1; // 0未満の場合、aをbより小さいインデックスにソート

        // タイトル（フォルダー名・タグ名）の昇順にソートする
        let nameA = a.name;
        let nameB = b.name;
        if (nameA < nameB) return -1;
        if (nameA > nameB) return 1;

        // URLの昇順にソートする
        let urlA = a.url.toUpperCase(); // 大文字と小文字を無視する
        let urlB = b.url.toUpperCase(); // 大文字と小文字を無視する
        if (urlA < urlB) return -1;
        if (urlA > urlB) return 1;

        return 0; // 0を返した場合、aとbは互いに変更せず、他のすべての要素に対してソート
    });
```
これでブックマーク情報を表示するための`dicTags`の準備ができました。

次回はブックマーク情報を表示する処理について解説します。

[[ソースコードを読む](#ソースコードを読む)へもどる]