Unity/Csharp/Json/JsonUtility
目次
jsonを扱い方
Unity 5.3からJsonUtilityが使えるようになったので、JsonUtilityを使う。
使いたいpropertyだけ定義すればそれだけを取得することもできる。
json展開
json
{"status":"ok","notice":"message1","user":{"id":1,"name":"taro","likes":["tyoko","prin"]}}
サンプル
using System; public class AuthScript : MonoBehaviour { [Serializable] class ResData { public string status = "ok"; public string notice = ""; public ResUser user; } [Serializable] class ResUser { public int id = 0; public string name = ""; public string[] likes; } void ExecJsonParse (string json) { ResData resData = JsonUtility.FromJson<ResData>(json); Debug.Log("status=" + resData.status); Debug.Log("notice=" + resData.notice); Debug.Log("user.name=" + resData.user.name); foreach (string like in resData.user.likes) { Debug.Log("like=" + like); } } }
以下エラーとなる場合は[Serializable]が足りない場合がある
NullReferenceException: Object reference not set to an instance of an object
[Serializable]を追加して以下エラーとなる場合はusing System;が足らない可能性がある。
error CS0246: The type or namespace name `Serializable' could not be found. Are you missing an assembly reference?
jsonからオブジェクトへ
User user = new User(); string json = JsonUtility.ToJson(user);
Listもjson対応させる方法
(unity6で、使えなくなった?と思ったが、やっぱり使えた・・。)
通常Listは[Serializable]が記述されていないため、json化できないが、リンク先のクラスを噛ませればできる。
Serialization.cs
using UnityEngine; using System.Collections; using System.Collections.Generic; using System; [Serializable] public class Serialization<T> { [SerializeField] List<T> target; public List<T> ToList() { return target; } public Serialization(List<T> target) { this.target = target; } }
UserにもSerializableなどがついてる必要がある
User.cs
[Serializable] public class User { [SerializeField] public string name = ""; [SerializeField] public int age = 0; }
呼び出し
string json = JsonUtility.ToJson(new Serialization<User>(users)); // {"target":[{"name":"taro","age":19}]} List<Enemy> users = JsonUtility.FromJson<Serialization<User>>(json).ToList();
参考:http://kou-yeung.hatenablog.com/entry/2015/12/31/014611
Dictionaryもjson対応させる方法
JsonUtilityはDictionaryに対応してないが、以下クラスを用意することで、対応で出来る。 ただし、json出力形式は、少し違うので、基本的にはDictionaryを、他で展開しないjson文字列として、保存する用に使うのかも。(NewtonJsonでは、通常のjson形式で、使えるので、そちらを使ったほうが良い)
Serialization.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; using System; [Serializable] public class Serialization<TKey, TValue> : ISerializationCallbackReceiver { [SerializeField] List<TKey> keys; [SerializeField] List<TValue> values; Dictionary<TKey, TValue> target; public Dictionary<TKey, TValue> ToDictionary() { return target; } public Serialization(Dictionary<TKey, TValue> target) { this.target = target; } public void OnBeforeSerialize() { keys = new List<TKey>(target.Keys); values = new List<TValue>(target.Values); } public void OnAfterDeserialize() { var count = Math.Min(keys.Count, values.Count); target = new Dictionary<TKey, TValue>(count); for (var i = 0; i < count; ++i) { target.Add(keys[i], values[i]); } } }
呼び出し
var dictionaryMsg = new Dictionary<int, string>() { { 1, "hoge" }, { 2, "piyo" }, }; var jsonDictionaryMsg = new Serialization<int, string>(dictionaryMsg); var json = JsonUtility.ToJson(jsonDictionaryMsg, true); Debug.Log(json); var jsonDictionaryMsgClone = JsonUtility.FromJson<Serialization<int, string>>(json); var dictionaryMsgClone = jsonDictionaryMsgClone.ToDictionary(); foreach (var x in dictionaryMsgClone) { Debug.Log(x.Key + ": " + x.Value); }
json形式
{ "keys": [ 1, 2 ], "values": [ "hoge", "piyo" ] }
参考:http://kou-yeung.hatenablog.com/entry/2015/12/31/014611
JSON parse error: Missingエラーが出るとき
以下エラーが出るとき
ArgumentException: JSON parse error: Missing a name for object member.
UnityEngine.JsonUtility.FromJson (System.String json, System.Type type) (at /Users/bokken/buildslave/unity/build/Modules/JSONSerialize/Public/JsonUtility.bindings.cs:42)
json内の'を"にしてあげると直った。以下コードで置換した。
json = json.Replace("'", "\"");
公式JsonUtility
https://docs.unity3d.com/ScriptReference/JsonUtility.html
他Jsonについて
Newtonsoft.Json を使ったJson.NETなどもある