サイト管理人Blog

cloudfreeで「さぁ始めましょう♪」

javascriptでJSONを読む

2023-11-26 記載
概要 : JSONを読んで中身を扱えるようにします。
Keyword : JSON, javascript, XMLHttpRequest, FileReader,

javascriptは書き方がいろいろあるので、Webでサンプルをみても2つと同じものがない感じです。とくにイベントや無名関数の書き方が多種あってわかりにくいです。宣言していない変数名が登場したり、同期非同期の=>でつなぐパイプライン的処理など、理屈では読みとけないソースです。

無名関数はなるべく使わない。同期が一瞬なら同期にする。不要な変数は受け取らない。変数を使うときは変数名は明瞭につける。という方針で、自分なりに納得できるコードを作成しました。

まずWebから取得のコード。fetchではなくXMLHttpRequestにしています。
htmlボタンClickで下のpreにJSON内容を出力します。

<input type="button" value="JSON" onclick="getJSON_Http()"/>
<pre id="jsonHttp" style="border:solid;"></pre>
function getJSON_Http() {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", "./chatgpt.json", false); // false=非同期
    xhr.setRequestHeader('Cache-Control', 'no-cache');
    xhr.send();
    var text = xhr.response;
    for (var [key, value] of jsonToMap(JSON.parse(xhr.response))) {
        text += "\r\n" + key + " : " + value;
    }
    document.getElementById("jsonHttp").innerText = text;
}

次にニーズは少ないかもしれませんがローカルからJSONファイルを読み込むコード。Firefoxでは
import jsondata from ‘./myfile.json’ assert {type: ‘json’};
はErrorになるので、このFileReaderを使う代替手段があります。

<input type="file" onchange="getJSON_File(this)"/>
<pre id="jsonFile" style="border:solid;">.jsonを選択</pre>
function getJSON_File(target_input) {
    const reader = new FileReader();
    reader.addEventListener("load", () => {
        var text = reader.result;
        for (var [key, value] of jsonToMap(JSON.parse(reader.result))) {
            text += "\r\n" + key + " : " + value;
        }
        document.getElementById("jsonFile").innerText = text;
    });
    reader.readAsText(target_input.files[0]);
}

forの3行はコメントアウトしても問題ありません。JSONデータをMapに格納するfunctionを呼んでいます。再帰関数なのでわかりにくいです。

function jsonToMap(json_object, prekey = "", mapItem = new Map()) {
    for(var key in json_object) {
        if (Array.isArray(json_object[key])) {
            for (var i = 0; i < json_object[key].length; i++) {
                jsonToMap(json_object[key][i], prekey + "/" + key + "[" + i + "]", mapItem);
            }
        } else if (typeof json_object[key] == "object") {
            jsonToMap(json_object[key], prekey + "/" + key, mapItem);
        } else {
            mapItem.set(prekey + "/" + key, json_object[key]);
        }
    }
    return mapItem; 
}

ChatGPT3.5にサンプルデータを作ってもらいました。
注文:
JSONデータのサンプルを作成してください。2段階のネストがあること。配列も使っていること。
回答:
もちろんです。以下は2段階のネストと配列を含むJSONデータの例です。

この例では、studentsというキーがあり、その配列に学生の情報が含まれています。各学生はidnameagecoursesというキーを持ち、courses内には複数の科目が配列として含まれています。


「もちろんです。」とな?
preのinnerTextは以下のように出力されます。Http,Fileのどちらでも。

{
  "students": [
    {
      "id": 1,
      "name": "田中太郎",
      "age": 20,
      "courses": [
        {
          "course_id": 101,
          "course_name": "数学"
        },
        {
          "course_id": 102,
          "course_name": "物理学"
        }
      ]
    },
    {
      "id": 2,
      "name": "山田花子",
      "age": 19,
      "courses": [
        {
          "course_id": 103,
          "course_name": "化学"
        },
        {
          "course_id": 104,
          "course_name": "生物学"
        }
      ]
    }
  ]
}

/students[0]/id : 1
/students[0]/name : 田中太郎
/students[0]/age : 20
/students[0]/courses[0]/course_id : 101
/students[0]/courses[0]/course_name : 数学
/students[0]/courses[1]/course_id : 102
/students[0]/courses[1]/course_name : 物理学
/students[1]/id : 2
/students[1]/name : 山田花子
/students[1]/age : 19
/students[1]/courses[0]/course_id : 103
/students[1]/courses[0]/course_name : 化学
/students[1]/courses[1]/course_id : 104
/students[1]/courses[1]/course_name : 生物学

前半がChatGPTコードと同じになるのは当たり前といえば当たり前。
([Object, Object]になってうんざりしていたのに↑こう云ってのける)

後半の
/students[0]/id : 1
……
/students[1]/courses[1]/course_name : 生物学
はMapから読みだしたものです。

投稿へのコメントは コチラ(掲示板) へお願いします。

サイト管理人Blog