JsonUtility
Unity には Json データを操作するクラスとして JsonUtility
がある
JsonUtility
は Primitive 型、Array、シリアライズ可能なクラス・構造体を Json 形式に変換できる
using System; using UnityEditor; using UnityEngine; [Serializable] public class JsonTest { public int IntVal; public string StrVal; public Vector2 Vector2Val; public Vector3Int Vector3IntVal; public int[] IntArray; public JsonTestSub SubClass; } [Serializable] public class JsonTestSub { public int IntVal; public string StrVal; } private static void ToJson() { var test = new JsonTest { IntVal = 10, StrVal = "str", Vector2Val = Vector2.one, Vector3IntVal = Vector3Int.left, IntArray = new []{ 0, 1, 2}, SubClass = new JsonTestSub { IntVal = 100, StrVal = "str", } }; Debug.Log(JsonUtility.ToJson(test, true)); }
例えば上記のコードを実行すると下記のJsonが取得できる
{ "IntVal": 10, "StrVal": "str", "Vector2Val": { "x": 1.0, "y": 1.0 }, "Vector3IntVal": { "x": -1, "y": 0, "z": 0 }, "SubClass": { "IntVal": 100, "StrVal": "str" }, "IntArray": [ 0, 1, 2 ] }
クラスに戻す場合は JsonUtility.FromJson<JsonTest>(json)
を利用する
意図していなかった挙動
先程の Json を作成する処理から JsonTestSub
クラス生成処理を削除しToJson
を行ってみる
private static void ToJson() { var test = new JsonTest { IntVal = 10, StrVal = "str", Vector2Val = Vector2.one, Vector3IntVal = Vector3Int.left, IntArray = new []{ 0, 1, 2}, }; Debug.Log(JsonUtility.ToJson(test, true)); }
これにより出力された Json は以下になる
{ "IntVal": 10, "StrVal": "str", "Vector2Val": { "x": 1.0, "y": 1.0 }, "Vector3IntVal": { "x": -1, "y": 0, "z": 0 }, "IntArray": [ 0, 1, 2 ], "SubClass": { "IntVal": 0, "StrVal": "" } }
見て分かるように SubClass のインスタンスを作成していない (null) にも関わらず、SubClass の Json が出力されている
ToJson
の呼び出し前後で SubClass のインスタンスを確認してみると
呼び出し前だと null なのに対し、呼び出し後では null では無くなっているため
JsonUtility.ToJson
内で対象クラスのクラスフィールドが null の場合内部でインスタンスを作成していると考えられる
private static void ToJson() { var test = new JsonTest { IntVal = 10, StrVal = "str", Vector2Val = Vector2.one, Vector3IntVal = Vector3Int.left, IntArray = new []{ 0, 1, 2}, }; Debug.Log(test.SubClass == null); // true Debug.Log(JsonUtility.ToJson(test, true)); Debug.Log(test.SubClass == null); // false }
not null の場合処理するような場合、ログ等でJsonUtlity
を利用していると
クラス内部のフィールド値がすべて default 値になってしまうので注意が必要です
注意
上記は Unity 2018.4.14f1 で確認しており、Unity 2019.2.9f1 で確認したところ ToJson
した際に
SubClass
は Json に含まれていたがインスタンスは null のままだったため、おそらく Unity 2019.1~ では修正された不具合だと思われる