13
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

UnityでJSONの構造を確認して、構造に応じた型へ変換する

Last updated at Posted at 2016-09-01

すごい広島 172のメモ
以下のJSONをUnityで読み込みたい。

{
	"type": "Point",
	"value": {
		"x": 1,
		"y": 2,
		"z": 3,
	}
}
{
	"type": "Press",
	"value": {
		"code": "a",
	}
}

typeによってvalueの中身が違うようなJSONです。
JsonUtilityではDictionary型への変換はできなくて、変換する先の型を用意する必要がある。
こういったタイプの読み込み型の方針については公式にもちゃんとかいてある。

型が未知の場合の FromJson() の使用

JSON を「共通」のフィールドを持つクラスか構造体にデシリアライズします。それから、そのフィールドの値を利用して、2 度目のデシリアライズで実際に求める型にします。

http://docs.unity3d.com/jp/current/Manual/JSONSerialization.html

ということで以下のような4つのクラスを用意する。

// typeを読むためのクラス
[Serializable]
class SeekJSONType {
	public string type;
}

// typeがわかった後に使うルート要素のクラス
[Serializable]
class Envelope<Value> {
	public string type;
	public Value value;
}

[Serializable]
class PointMessage {
	public float x;
	public float y;
	public float z;
}

[Serializable]
class PressMessage {
	public string code;
}

以下のように使う

var seekType = JsonUtility.FromJson<SeekJSONType>(str);
switch (seekType.type) {
	case "Point":
		var point = JsonUtility.FromJson<Envelope<PointMessage>>(str);
		// pointを使った処理
		break;
	case "Press": {
		var press = JsonUtility.FromJson<Envelope<PressMessage>>(str);
		// pressを使った処理
		break;
	}
}

実行例

コード。

using UnityEngine;
using System.Collections;

using System;

// typeを読むためのクラス
[Serializable]
class SeekJSONType {
	public string type;
}

// typeがわかった用のルート要素のクラス
[Serializable]
class Envelope<Value> {
	public string type;
	public Value value;
}

[Serializable]
class PointMessage {
	public double x;
	public double y;
	public double z;
}

[Serializable]
class PressMessage {
	public string code;
}


public class JsonFromSample : MonoBehaviour {

	// Use this for initialization
	void Start () {
		read ("{\"type\":\"Point\",\"value\":{\"x\":1,\"y\": 2,\"z\":3}}");
		read ("{\"type\":\"Press\",\"value\":{\"code\":\"a\"}}");
	}

	void read (string jsonString) {
		var seekType = JsonUtility.FromJson<SeekJSONType>(jsonString);
		switch (seekType.type) {
		case "Point":
			var point = JsonUtility.FromJson<Envelope<PointMessage>> (jsonString).value;
			Debug.Log (String.Format("Point<{0},{1},{2}>", point.x, point.y, point.z));
			break;
		case "Press":
			var press = JsonUtility.FromJson<Envelope<PressMessage>>(jsonString).value;
			Debug.Log (String.Format("Press<{0}>", press.code));
			break;
		}
	}
	
	// Update is called once per frame
	void Update () {
	
	}
}

実行結果。

Kobito.BWSJaU.png

感想

ジェネリクスが使えてちょっと楽ができた。
switchが文字列でも使えてちょっと楽ができた。
C#細かいところわからないので、Scalaでかけたらいいなって個人的には思った。

参考

13
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?