facebook twitter hatena line email

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などもある

https://yubeshicat.hatenablog.com/entry/2019/11/02/180914