facebook twitter hatena line email

「Unity/Csharp/Json/JsonUtility」の版間の差分

提供: 初心者エンジニアの簡易メモ
移動: 案内検索
(ページの作成:「 ==jsonを扱い方== Unity 5.3からJsonUtilityが使えるようになったので、JsonUtilityを使う。 使いたいpropertyだけ定義すればそれだけを...」)
 
 
(同じ利用者による、間の5版が非表示)
行1: 行1:
 
 
==jsonを扱い方==
 
==jsonを扱い方==
 
Unity 5.3からJsonUtilityが使えるようになったので、JsonUtilityを使う。
 
Unity 5.3からJsonUtilityが使えるようになったので、JsonUtilityを使う。
行37: 行36:
 
以下エラーとなる場合は[Serializable]が足りない場合がある
 
以下エラーとなる場合は[Serializable]が足りない場合がある
 
  NullReferenceException: Object reference not set to an instance of an object
 
  NullReferenceException: Object reference not set to an instance of an object
 
  
 
[Serializable]を追加して以下エラーとなる場合はusing System;が足らない可能性がある。
 
[Serializable]を追加して以下エラーとなる場合はusing System;が足らない可能性がある。
行47: 行45:
  
 
==Listもjson対応させる方法==
 
==Listもjson対応させる方法==
 +
(unity6で、使えなくなった?と思ったが、やっぱり使えた・・。)
 +
 
通常Listは[Serializable]が記述されていないため、json化できないが、リンク先のクラスを噛ませればできる。
 
通常Listは[Serializable]が記述されていないため、json化できないが、リンク先のクラスを噛ませればできる。
  
行82: 行82:
 
}
 
}
 
</pre>
 
</pre>
 
  
 
呼び出し
 
呼び出し
行88: 行87:
 
string json = JsonUtility.ToJson(new Serialization<User>(users)); //  {"target":[{"name":"taro","age":19}]}
 
string json = JsonUtility.ToJson(new Serialization<User>(users)); //  {"target":[{"name":"taro","age":19}]}
 
List<Enemy> users = JsonUtility.FromJson<Serialization<User>>(json).ToList();
 
List<Enemy> users = JsonUtility.FromJson<Serialization<User>>(json).ToList();
 +
</pre>
 +
 +
参考:http://kou-yeung.hatenablog.com/entry/2015/12/31/014611
 +
 +
==Dictionaryもjson対応させる方法==
 +
JsonUtilityはDictionaryに対応してないが、以下クラスを用意することで、対応で出来る。
 +
ただし、json出力形式は、少し違うので、基本的にはDictionaryを、他で展開しないjson文字列として、保存する用に使うのかも。(NewtonJsonでは、通常のjson形式で、使えるので、そちらを使ったほうが良い)
 +
 +
Serialization.cs
 +
<pre>
 +
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]);
 +
        }
 +
    }
 +
}
 +
</pre>
 +
 +
呼び出し
 +
<pre>
 +
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);
 +
}
 +
</pre>
 +
===json形式===
 +
<pre>
 +
{
 +
    "keys": [
 +
        1,
 +
        2
 +
    ],
 +
    "values": [
 +
        "hoge",
 +
        "piyo"
 +
    ]
 +
}
 
</pre>
 
</pre>
  

2024年9月15日 (日) 00:39時点における最新版

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