[Unity][MiniJSON]JSONデータを読み込む

  • SumoMe

JSONのデータの読み込みをMiniJSONを利用して行います。

JSONとは

以前説明しましたので、下記のページの同名の章を参照してください。

[Processing] JSONの読み込み書き込み

MiniJSON利用準備

今回はMiniJSONというC#で書かれた、軽量なJSONパーサを利用します。MITライセンスです。

インストール

MiniJSONを以下のページからダウンロードします。


https://gist.github.com/darktable/1411710

  1. 上記のページの「Download Gist」ボタンを押し、圧縮ファイルをダウンロードします。ファイルを解凍し、ディレクトリ中の「MiniJSON.cs」を取り出します。

  2. ProjectウインドウのAsset内に「Plugins」というディレクトリを作成し、このディレクトリにMiniJSON.csをコピーする

以上で利用が可能になります。

スクリプトから利用する

利用するスクリプトには以下のソースのように、

  • using MiniJSON;
  • using System.Collections.Generic;

の二行を、ファイルの先頭のほうに追加してください。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using MiniJSON;

public class JSONReadSample : MonoBehaviour {
....

JSONデータのパース(解析)

使用するJSONデータ

JSONのデータは以前例題に利用した家族のデータを利用します。

[Processing] JSONの読み込み書き込み

上のページの「構造化する」の項にある、「person.json」の内容を読み込んでみましょう。今回は簡単にするために、このデータをソースコードの中に組み込んでしまいました。

まずは出来上がった読み込みスクリプトです。

public class JSONReadSample : MonoBehaviour {
	// Use this for initialization
	void Start () {
		GetJSON();
	}
	
	void GetJSON(){
		// JSONフォーマットデータを文字列として、文字列変数「json」に保持
		string json = "["+
    					"{"+
        					"\"name\":\"son\","+
        					"\"age\":21,"+
        					"\"hobby\":[\"baseball\",\"car\"]"+
    					"},"+
    					"{"+ 
        					"\"name\":\"daughter\","+
        					"\"age\":18,"+
					        "\"hobby\":[\"shopping\",\"tv game\"]"+
					    "},"+
					    "{"+ 
					        "\"name\":\"daddy\","+
					        "\"age\":42,"+
					        "\"hobby\":[\"car\",\"fishing\"]"+
					    "}"+
					"]";
		// JSONデータは最初は配列から始まるので、Deserialize(デコード)した直後にリストへキャスト		
		IList familyList = (IList)Json.Deserialize(json);
		// リストの内容はオブジェクトなので、辞書型の変数に一つ一つ代入しながら、処理
		foreach(IDictionary person in familyList){
			// nameは文字列なので、文字列型へキャストしてから変数へ格納
			string name = (string)person["name"];
			Debug.Log("name:"+name);
			// ageは整数型なので、long型にキャストしてから変数へ格納
			long age = (long)person["age"];
			Debug.Log("age:"+age);
			// hobbyは配列なので、リストにキャストしてから、変数へ格納
			IList hobbes = (IList)person["hobby"];
			// 配列の内容は文字列なので、文字列変数に一つ一つ代入しながら、処理
			foreach(string hobby in hobbes){
				Debug.Log("hobby:"+hobby);
			}
		}
	}
}

以上のスクリプト「JSONReadeSample.cs」を適当なオブジェクトに付加し、実行すると、コンソールに以下のような内容が表示され、JSONデータが解析され表示されていることが確認できます。ちなみに、表示はDebug.Logメソッドを利用しました。

familyoutput

コメントに大部分は書いてしまいましたので、割愛しますが、重要な点を挙げておきます。

  • Json.Deserialize(デコード)するJSONデータは文字列型を利用する
  • すべてのデータはObjectクラスになっているため、代入にはキャストが必要
  • オブジェクト( {, })はIDictionary(辞書)型へ(29行目)
  • 配列([, ])はIList(リスト)型へ(27,37行目)
  • 整数はlong型(32行目)、実数はdouble型
  • 文字列はstring型(31,39行目)

以上のルールさえ把握すれば、読込は難しくはありません。

Webサーバから取得する

JSONデータをWebブラウザから取得し、上記のJSONのパースを実行します。Webサーバから取得する情報はperson.jsonと同じ内容です。

アクセスするアドレスは : http://www.cho-design-lab.com/download/samplejson.phpです。ブラウザでアクセスし、一度内容を確認してください。

Webサーバから情報を取得する場合は、Unity標準のWWWクラスが便利です。


http://docs.unity3d.com/Documentation/ScriptReference/WWW.html

利用方法は上記の公式サイトにサンプルがありますので、参考にしてください。定義するメソッドの戻り値の型が「IEnumrator」となるメソッドは、コルーチンと呼ばれる機能で利用されるメソッドです。参考までに、本ページの末項に参考サイトを記載します。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using MiniJSON;

public class JSONReadSampleWeb : MonoBehaviour {
// Use this for initialization
	void Start () {
		// コルーチン実行開始
		StartCoroutine("GetJSON");
	}
	
	IEnumerator GetJSON(){
		// webサーバへアクセス
		WWW www = new WWW("http://www.cho-design-lab.com/download/samplejson.php");
		// webサーバから何らかの返答があるまで停止
		yield return www;
		// もし、何らかのエラーがあったら
		if(!string.IsNullOrEmpty(www.error)){
			// エラー内容を表示
			Debug.LogError(string.Format("Fail Whale!\n{0}", www.error));
			yield break; // コルーチンを終了
		}
		// webサーバからの内容を文字列変数に格納
		string json = www.text; 
		// 以降JSONのパースは同じ	
		IList familyList = (IList)Json.Deserialize(json);
		
		foreach(IDictionary person in familyList){
			string name = (string)person["name"];
			Debug.Log("name:"+name);
			
			long age = (long)person["age"];
			Debug.Log("age:"+age);
			
			IList hobbes = (IList)person["hobby"];
			foreach(string hobby in hobbes){
				Debug.Log("hobby:"+hobby);
			}
		}
	}
}

結果は以前のものとまったく同じです。

webサーバへアクセスし、返答にエラーがあった場合エラー内容が表示されます。以下は、アドレスを故意に間違えた場合の実行結果です。

urlmiss

実用的な例

今までの例では、パースした情報を表示しただけでした。そこで今回は以下のJSONデータを読み込んで、オブジェクトを作成してみます。

JSONデータ

今回読み込むJSONデータは以下のとおりです。

[
 {
   "name":"sphere1",
     "position":[0.0,0.0,0.0],
     "scale":[1.0,1.0,1.0]
     },
 {
   "name":"sphere2",
     "position":[5.0,0.0,0.0],
     "scale":[0.5,0.5,0.5]
     },
 {
   "name":"sphere3",
     "position":[0.0,5.0,0.0],
     "scale":[2.0,2.0,2.0]
     }
]

このデータは、オブジェクトデータの配列です。オブジェクトデータには、名前(name)、位置(position)、拡大縮小(scale)を記録してあり、この数値を使ってオブジェクトに名前、位置、拡大縮小を支持します。

準備

今回は、オブジェクトを生成しますので、生成するためのオブジェクトを用意します。今回用意するオブジェクトは、球オブジェクトを利用します。このままでは生成するためには適さないので、この球をプレハブ化しました。

spherePrefab

C# Script を作成し、「JSONReadSphereWeb」とします。このスクリプトファイルは以下のようになります。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using MiniJSON;

public class JSONReadSphereWeb : MonoBehaviour {
	public GameObject prefab;
	// Use this for initialization
	void Start () {
		StartCoroutine("createPrefabsFromJSON");
	}
	
	IEnumerator createPrefabsFromJSON(){
		WWW www = new WWW("http://www.cho-design-lab.com/download/spheres.php");
		yield return www;
		
		if(!string.IsNullOrEmpty(www.error)){
			Debug.LogError(string.Format("Fail Whale!\n{0}", www.error));
			yield break;
		}
		
		string json = www.text; 
		
		IList spheres = (IList)Json.Deserialize(json);
		foreach(IDictionary sphere in spheres){
			// オブジェクトを生成
			GameObject obj = (GameObject) Instantiate(prefab);
			// 名前を設定
			obj.name = (string)sphere["name"];
			
			// 位置を設定
			IList positionList = (IList)sphere["position"];
			Vector3 pos = new Vector3(
				(float)((double)positionList[0]),
				(float)((double)positionList[1]),
				(float)((double)positionList[2]));
			obj.transform.position = pos;
			
			// 拡大縮小を設定
			IList scaleList = (IList)sphere["scale"];
			Vector3 scale = new Vector3(
				(float)((double)scaleList[0]),
				(float)((double)scaleList[1]),
				(float)((double)scaleList[2]));
			obj.transform.localScale = scale;
		}
	}
}

このスクリプトを適当なオブジェクトに付加し、Inspectorから球のプレハブオブジェクトを変数「prefab」に渡します。

inscpectoPrefab

実行結果

準備を整え、実行ボタンを押すと、以下の図のような結果になります。

runningJsonSphere

また実行時には、HierarchyウインドウではJSONで指定されたnameがオブジェクトの名前となっています。

jsonHierarcht

このような仕組みにしておけば、JSONデータを編集するだけで、オブジェクトの追加や変更ができます。

おわりに

今回はJSONデータを読込みパースしました。そのために、「MiniJSON」というライブラリを利用しました。また、パースしたデータから生成したオブジェクトに設定を与えることが出来ました。このように、外部ファイルを自由に読み込めるようにしておけば、様々なシーンで柔軟に対応することができます。

参考

MiniJSON script for parsing JSON data
http://forum.unity3d.com/threads/35484-MiniJSON-script-for-parsing-JSON-data

[Unity3D]Unity非同期処理デザインについて
http://terasur.blog.fc2.com/?tag=Coroutine

[Unity][MiniJSON]JSONデータを読み込む” への1件のコメント

  1. How to use where clause (Pass parameter value) in MiniJSON

    I have 2 array names called categories and products and i’m getting the values from products table but i want to pass the id value from categories to products using WHERE clause. But how can i use WHERE in MiniJSON?

    {“Categories”:[{“id”:”1″,”name”:”Test1″},{“id”:”2″,”name”:”Test2″},}],

    “Products”:
    [{“name”:”Test2″,”category_id”:”2″,”imageurl”:”http://server.com/3DModel_images/Xpl.jpg”},
    {“name”:”Test1″,”category_id”:”1″,”imageurl”:”http://server.com/3DModel_images/favicon.jpg”},]}

    IList linksObject = (IList) search[“Products”]

    foreach (IDictionary ProductslinksArray in linksObject) {

    String modal3d=string.Format(“{0} “, ProductslinksArray[“imageurl”]);

    //Here i need to pass the id value from categories to products WHERE category_id=? (id value ) How can i use WHERE clause?

    I have tried below

    String cat_id=string.Format(“{0} “, modellinksArray[“category_id”]);

    String modal3d=string.Format(“{0} “, modellinksArray[“imageurl”] as cat_id[“1”]);

    }

コメントは受け付けていません。