11_2:JSONデータ p5.js JavaScript

JSON(JavaScript Object Notation)形式もまた、データの保持によく使用されるシステムです。HTMLやXML形式のように、要素はそれに関連付けられたラベルを持ちます。たとえば、映画のデータを表すラベルとして、題名や監督名、公開日、レート(年齢制限)などが考えられるでしょう。これらのラベルは次のように、そのデータとペアで関連付けられます。

    "title": "Alphaville",
    "director": "Jean-Luc Godard",
    "year": 1964,
    "rating": 7.2

JSONファイルとして機能させるには、要素を区切る点がもう少し必要で、データのペアを区切るカンマと、全体を囲む中かっこ({と})が使用されます。有効なJSONデータは次のように表わされます。

{
    "title": "Alphaville",
    "director": "Jean-Luc Godard",
    "year": 1964,
    "rating": 7.2
}

この短いJSONサンプルには、データ型に関する興味深い詳細があります。題名と監督名のデータは、それが文字列であることを示すために引用符で囲まれ、公開年とレートのデータは、それが数値であ示すために引用符で囲まれていないことに気づかれたでしょうか? この違いは、データをスケッチに読み込んだ後、重要になります。

リストに映画をもう1つ追加するには、上下を角かっこ([と])で囲み、データがJSONオブジェクトの配列であることを示し、{と}で囲んだオブジェクトをカンマで区切ります。まとめると次のようになります。

[
  {
      "title": "Alphaville",
      "director": "Jean-Luc Godard",
      "year": 1964,
      "rating": 7.2
  }, 
  {
    "title": "Pierrot le Fou",
    "director": "Jean-Luc Godard",
    "year": 1965,
    "rating": 7.7
  }
]

このパターンはもっと多くの映画にも同様に繰り返すことができます。ここで、JSON記法と、それと同じデータを表す表表現を比べると、面白いことが分かります。CSVファイルは次のように表されます。

title, director, year, rating 
Alphaville, Jean-Luc Godard, 1965, 9.1 
Pierrot le Fou, Jean-Luc Godard, 1965, 7.3 

CSV記法の方が文字数が少ないのです。これは、大量のデータを扱うときに重要になります。これに対しJSONの方は、データにラベル付けがされているので、CSV形式よりも読みやすいことが分かります。

JSPNファイルの読み取り

下記コードを記述したfilm.jsonを読み込み、データを取り出す基本的な例です。

{
  "title": "Alphaville",
  "director": "Jean-Luc Godard",
  "year": 1964,
  "rating": 7.2
}
let film;

function preload() {
    film = loadJSON('film.json');
}

function setup() {
    const title = film.title;
    const dir = film.director;
    const year = film.year;
    const rating = film.rating;
    print(title + " by " + dir + ", " + year + ", Rating: " + rating);
}

読み込んだJSONオブジェクトのデータには、オブジェクトのプロパティにアクセスするのと同じドット演算子でアクセスできます。

JSONデータの視覚化

次はいささかテクニカルに走った例で、複数の映画情報を含むJSONファイルを読み込み、それぞれの情報を、映画用のクラスを使ってキャンバスに描画します。

const films = [];
let filmData;

function preload() {
    // 複数の映画情報を含むJSONファイルを読み込む
    filmData = loadJSON('films.json');
}

function setup() {
    createCanvas(480, 120);
    noStroke();
    // 含まれるデータ数を特定する
    const len = Object.keys(filmData).length;
    // データ数分だけループ処理
    for (let i = 0; i < len; i++) {
        // JSONオブジェクトを1つずつ取り出し、Filmクラスに渡してFilmオブジェクトを作成し、
        // 配列filmsに入れる
        const o = filmData[i];
        films[i] = new Film(o);
    }

}

function draw() {
    background(0);
    // films配列に入れたFilmオブジェクトに順にアクセスし、
    // display()メソッドを実行する
    for (let i = 0; i < films.length; i++) {
        const x = i * 32 + 32;
        films[i].display(x, 105);
    }
}

// Filmクラス
class Film {
    constructor(f) {
        // オブジェクトの生成時に、渡された情報を自分のプロパティとして保持する
        this.title = f.title;
        this.director = f.director;
        this.year = f.year;
        this.rating = f.rating;
    }

    // 自分の映画情報を表示
    display(x, y) {
        const ratingGray = map(this.rating, 6.5, 8.1, 102, 255);
        push();
        translate(x, y);
        rotate(-QUARTER_PI);
        fill(ratingGray);
        text(this.title, 0, 0);
        pop();
    }
}

ネットワークデータ

Weather API」サイトでは、ユーザー登録で得られるAPI Keyを使って、世界中のさまざまな地域の天気情報をJSON形式で返すサービスが提供されています。

以下は天気情報を得てそれを表示する例です。参考「Weather

HTML

<div>
  <h4>天気情報</h4>
  <ul>
    <li>観測日時:<span id="date"></span> 場所:<span id="place"></span></li>
    <li>天気:<span id="current-weather"></span>
      <div id="image-holder"><img id="icon"></div>
    </li>
    <li>気温:<span id="temperature"></span> 湿度:<span id="humidity"></span></li>
    <li>風速:<span id="wind"></span> 風向:<span id="wind-dir"></span></li>
    <li>風向きの角度:<span id="wind-degree"></span></li>
  </ul>
</div>
<script src="sketch.js"></script>

sketch.js

// apixu.comから返される天気情報のJSONデータ
let weather;
// 風向きのベクトル
let wind;

function setup() {
    const canvas = createCanvas(80, 80);
    canvas.position(240, 120);
    // apixu.comに天気情報をリクエスト
    let url = 'https://api.apixu.com/v1/current.json?key=取得したAPIKEY&q=地域名&lang=ja'
    loadJSON(url, gotWeather);

    // (0, 0)のベクトル
    wind = createVector();
    print(wind.x);
    print(wind.y);
}

function draw() {
    background(204);

    // 風向きを示す矢印を描画
    translate(40, 40);
    // 風向き分、座標軸を回転
    // 	風向きベクトルの回転の角度を計算
    rotate(wind.heading());

    // センターの白い円
    noStroke();
    fill(255);
    ellipse(0, 0, 60, 60);
    // 棒
    stroke(45, 123, 182);
    strokeWeight(3);
    line(0, -16, 0, 16);
    // 三角形
    noStroke();
    fill(45, 123, 182);
    triangle(0, -18, -6, -10, 6, -10);
}

function gotWeather(w) {
    weather = w;
    print(weather);
    /* 各天気情報へのアクセス方法
    print(weather.current.last_updated);
    print(weather.location.name);
    print(weather.current.condition.text);
    print(weather.current.temp_c);
    print(weather.current.humidity);
    print(weather.current.wind_dir);
    print(weather.current.wind_degree);
    print(weather.current.wind_kph);
    print(weather.current.condition.icon)
    */
    // 返されたデータから情報を取り出してページに表示
    select('#date').html(weather.current.last_updated);
    select('#place').html(weather.location.name);
    select('#current-weather').html(weather.current.condition.text);
    select('#temperature').html(weather.current.temp_c + '&deg;');
    select('#humidity').html(weather.current.humidity + '%');
    select('#wind').html((weather.current.wind_kph * 5 / 18).toFixed(1) + ' m/s');
    select('#wind-dir').html(weather.current.wind_dir);
    select('#icon').elt.src = 'https://' + weather.current.condition.icon;
    select('#wind-degree').html(weather.current.wind_degree + '度');

    // 風向きの角度をラジアンに変換
    const angle = radians(Number(weather.current.wind_degree));
    // 角度から新しいベクトルを作成
    wind = p5.Vector.fromAngle(angle);
    print(wind);
}

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA