【Unity】JsonUtility 注意事項

22 7月, 2018

【Unity】JsonUtility 注意事項




在Unity開發多少會碰到需要解析JSON文檔的方式
Unity本身也有自帶一個輕量級
效能也高的JSON解析類庫 - 「JsonUtility




以下是官方的文檔說明
https://docs.unity3d.com/ScriptReference/JsonUtility.html

使用上相對也簡單。

不過由於這個類庫是屬於輕量級的類庫。
很多較複雜的功能都不支援。

以下是使用的注意事項:

(1)不支援自定義屬性
像是JAVA的Gson等等之類的類庫
都可以自定義反序列跟序列化的屬性


但是JsonUtility沒有SerializedName這種類似的功能

屬性名稱需要與來源資料一致
也就是key需要一致
假設來源資料如下
{
"v_string": "112",
"v_bool": true,
"v_double": 1.3554999828338623,
"data": [
2,
3,
4
]
}
view raw testData.json hosted with ❤ by GitHub
則結構也需要如此定義

using System;
using System.Collections.Generic;
[System.Serializable]
public class Data
{
public string v_string;
public bool v_bool;
public double v_double;
public List<int> data;
}
view raw data.cs hosted with ❤ by GitHub

(2) 需要"序列化/反序列化"的屬性須為public
JsonUtility是使用屬性公開與否
來判斷是否要該屬性序列化或反序列化
另外被序列化的資料,內容屬性排序是跟你物件定義的排序是一致的。


(3)解析泛型結構有瑕疵
JsonUtility 是支持泛型結構的
但是當泛型結構到第二層的時候,
解析上是會有問題的。

假設定義一個泛型資料物件
using UnityEngine;
[System.Serializable]
public class TestData<T>
{
public int code;
public T data;
}
view raw TestData.cs hosted with ❤ by GitHub

using System;
using System.Collections.Generic;
[System.Serializable]
public class Data
{
public string v_string;
public bool v_bool;
public double v_double;
public List<int> data;
}
view raw data.cs hosted with ❤ by GitHub
當只包裝一層的時候,UNITY解析是可以正常的。
List<int> _test = new List<int>();
_test.Add(2);
_test.Add(3);
_test.Add(4);
//Data物件
Data Data_No_T = new Data();
Data_No_T.v_bool = true;
Data_No_T.v_string = "112";
Data_No_T.v_double = 1.3555f;
Data_No_T.data = _test;//塞入資料
Debug.Log("Data_No_T:" + JsonUtility.ToJson(Data_No_T));
// TestData<T> 泛型物件
TestData<Data> testDataNoT = new TestData<Data>();
testDataNoT.code = 200;
testDataNoT.data = Data_No_T;
Debug.Log("testData(NO T):" + JsonUtility.ToJson(testDataNoT));
//print:testData(NO T):{"code":200,"data":{"v_string":"112","v_bool":true,"v_double":1.3554999828338624,"data":[2,3,4]}}
view raw DMEO.CS hosted with ❤ by GitHub

但假設今天如果有另一個資料也是泛型物件呢?
也就是解析資料的時候,變成二層以上的泛型物件解析
如下:
using System;
[System.Serializable]
public class DataT<T>
{
public int v_int;
public string v_string;
public bool v_bool;
public double v_double;
public T data;
}
view raw dataT.cs hosted with ❤ by GitHub



List<int> _test = new List<int>();
_test.Add(2);
_test.Add(3);
_test.Add(4);
//將LIST物件直接塞入
DataT<List<int>> Data_T = new DataT<List<int>>();
Data_T.v_int = 1;
Data_T.v_bool = false;
Data_T.v_string = "111";
Data_T.v_double = 1.2555f;
Data_T.data = _test;
Debug.Log("Data_T:" + JsonUtility.ToJson(Data_T));
TestData<DataT<List<int>>> testData = new TestData<DataT<List<int>>>();
testData.code = 200;
testData.data = Data_T;
Debug.Log("testData(T):" + JsonUtility.ToJson(testData));
//print {"code":200}
view raw demoT.cs hosted with ❤ by GitHub
會發現,解析上後面的泛型物件會直接無法被解析出來
到第二層以後的泛型物件,會導致解析有問題

附上DEMO的檔案
https://drive.google.com/open?id=1ppzAJOIXZK-rMTL4CkyaUEju82SN_Off




張貼留言