前往
大廳
主題

【Unity紀錄】有關於Json和Json Array在Unity中的Serialize and Deserialize的一些二三事

高雄鐵道具象 | 2021-01-19 19:11:30 | 巴幣 206 | 人氣 4195

1.什麼是Json?
JSON(JavaScript Object Notation) 是一種輕量級的資料交換格式。它基於ECMAScript的一個子集。 JSON採用完全獨立於語言的文字格式,但是也使用了類似於C語言家族的習慣(包括C、C 、C#、Java、JavaScript、Perl、Python等)。這些特性使JSON成為理想的資料交換語言。 易於人閱讀和編寫,同時也易於機器解析和生成(一般用於提升網路傳輸速率)。
2.JSON 語法規則
–資料在鍵值對中
–資料由逗號分隔
–花括號儲存物件
–方括號儲存陣列
舉例:
{
    "health": 100.0,
    "money": 2500,
    "Turing": [
        "sword",
        "shield",
        "gun",
        "woman",
        "fruit"
    ]
}

3.Json的結構
–物件:物件在js中表示為“{}”括起來的內容,資料結構為 {key:value,key:value,…}的鍵值對的結構,在物件導向的語言中,key為物件的屬性,value為對應的屬性值,所以很容易理解,取值方法為 物件.key 獲取屬性值,這個屬性值的型別可以是 數字、字串、陣列、物件幾種。
–陣列:陣列在js中是中括號“[]”括起來的內容,資料結構為 [“java”,”javascript”,”vb”,…],取值方式和所有語言中一樣,使用索引獲取,欄位值的型別可以是 數字、字串、陣列、物件幾種。

開始實作:
Serialize模式A

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;

public class JsonDemo2 : MonoBehaviour
{
    //要儲存的物件或是陣列用一個Class去儲存,裡面可以放各類型的資料
    [SerializeField]
    public class Data2
    {
        public float health;
        public int money;
        public List<string> Turing;
    }
    void Start()
    {
        //宣告一個List作為道具列表並存入四個物件
        List<string> equips = new List<string>();
        equips.Add("sword");
        equips.Add("shield");
        equips.Add("gun");
        equips.Add("woman");
        equips.Add("fruit");

        //用剛剛宣告好的Class創建一個儲存數值的物件,並給予數值欄位對應的數值(例如生命設定為100,金錢2500....)

        //↓方法1
        //Data2 newData = new Data2
        //{
        //    health = 100,
        //    money = 2500,
        //    Turing = equips
        //};


        //↓方法2  兩種方法輸出結果皆相同
        Data2 newData = new Data2();
        newData.health = 100;
        newData.money = 2500;
        newData.Turing = equips;


        //把剛剛創建好的數值物件轉為Json字串,並用JsonInfo參數儲存(模式A有bool prettyprint)
        string jsonInfo = JsonUtility.ToJson(newData, true);


        Debug.Log("寫入完成");
        //接下來把這個字串寫入指定的檔案位置(下面紅色字請改成自己的路徑《都可以》最後面是檔案名稱)
        File.WriteAllText("D:/20193DRowingVR/Mirro3DRowingUnity20194_ThirdPerson/Assets/file55688", jsonInfo);

        Debug.Log(jsonInfo);
      
    }
}
來看看輸出結果

Serialize模式B

//把剛剛創建好的數值物件轉為Json字串,並用JsonInfo參數儲存(模式B無bool prettyprint)
        string jsonInfo = JsonUtility.ToJson(newData);


        Debug.Log("寫入完成");
        //接下來把這個字串寫入指定的檔案位置(下面紅色字請改成自己的路徑《都可以》最後面是檔案名稱)
        File.WriteAllText("D:/20193DRowingVR/Mirro3DRowingUnity20194_ThirdPerson/Assets/file55688", jsonInfo);

        Debug.Log(jsonInfo);
來看看輸出結果

接著來看看以JsonUility為主的3種deserialize(反序列化)
Deserialize模式A

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;


public class JsonLoad : MonoBehaviour
{
    //宣告一個字串讀取檔案,宣告一個Data物件,來取得字串轉換後的物件
    string LoadData;
    JsonDemo2.Data MyData;
    void Start()
    {

        //讀取指定路徑的Json檔案並轉成字串
        LoadData = File.ReadAllText("D:/20193DRowingVR/Mirro3DRowingUnity20194_ThirdPerson/Assets/file55688");

        //把字串轉換成Data物件
        JsonDemo2.Data MyData = JsonUtility.FromJson<JsonDemo2.Data>(LoadData);

        Debug.Log("Deserialize模式A");
        Debug.Log("玩家生命為 " + MyData.health);
        Debug.Log("玩家金錢為 " + MyData.money);
        Debug.Log("玩家有" + MyData.Turing.Count + "個裝備");

    }
}

Deserialize模式B

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;


public class JsonLoad2 : MonoBehaviour
{
    //宣告一個字串讀取檔案,宣告一個Data物件,來取得字串轉換後的物件
    string LoadData;
    JsonDemo2.Data MyData;

    void Start()
    {
        //讀取指定路徑的Json檔案並轉成字串
        LoadData = File.ReadAllText("D:/20193DRowingVR/Mirro3DRowingUnity20194_ThirdPerson/Assets/file55688");

        //使用public static object FromJson(string json,Type type)來反序列化
        MyData = (JsonDemo2.Data)JsonUtility.FromJson(LoadData, typeof(JsonDemo2.Data));

        Debug.Log("Deserialize模式B");
        Debug.Log("玩家生命為 " + MyData.health);
        Debug.Log("玩家金錢為 " + MyData.money);
        Debug.Log("玩家有" + MyData.Turing.Count + "個裝備");

    }
}

Deserialize模式C

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;

public class JsonLoad3 : MonoBehaviour
{
    string LoadData;
    JsonDemo2.Data MyData;
    
    void Start()
    {
        MyData = new JsonDemo2.Data();
        deserialize();
    }

    // 將deserialize()設為一個反序列化用的物件
    void deserialize()
    {
        //讀取指定路徑的Json檔案並轉成字串
        LoadData = File.ReadAllText("D:/20193DRowingVR/Mirro3DRowingUnity20194_ThirdPerson/Assets/file55688");

        //使用public static void FromJsonOverwrite(string json,object objectToOverwrite)來反序列化
        JsonUtility.FromJsonOverwrite(LoadData, MyData);

        Debug.Log("Deserialize模式C");
        Debug.Log("玩家生命為 " + MyData.health);
        Debug.Log("玩家金錢為 " + MyData.money);
        Debug.Log("玩家有" + MyData.Turing.Count + "個裝備");
    }
}

三種模式的輸出結果


數組序列化
由於當前JsonUility不支援數組序列化,因此需要借助外掛來幫助列化的儲存和讀取,如:SimpleJSON或是JsonHelper。
JsonHelper儲存
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System;

public class JsonArrayDemo : MonoBehaviour
    
{
    //要儲存的物件或是陣列用一個Class去儲存,裡面可以放各類型的資料
    //[Serializable]一般除了使陣列可以在inspector中序列化並顯示,在這邊一定要加,沒有的話JsonUility無法序列化數組的Json

    [Serializable]
    public class ArrayData
    {
        public float Health;
        public int Money;
        public string Level;
        public List<string> Turing;
    }



    //Json如包含多個數據對象,例如Health出現了不止一次,由於UnityJsonUtility尚不支持數組,但是可以使用此幫助程序類使數組與JsonUtility一起運作。
    //創建一個名為JsonHelper的class。直接複製下面的JsonHelper。

    public static class JsonHelper
    {
        public static T[] FromJson<T>(string jsonArray)
        {
            jsonArray = WrapArray(jsonArray);
            return FromJsonWrapped<T>(jsonArray);
        }

        public static T[] FromJsonWrapped<T>(string jsonObject)
        {
            Wrapper<T> wrapper = JsonUtility.FromJson<Wrapper<T>>(jsonObject);
            return wrapper.items;
        }

        private static string WrapArray(string jsonArray)
        {
            return "{ \"items\": " + jsonArray + "}";
        }

        public static string ToJson<T>(T[] array)
        {
            Wrapper<T> wrapper = new Wrapper<T>();
            wrapper.items = array;
            return JsonUtility.ToJson(wrapper);
        }

        public static string ToJson<T>(T[] array, bool prettyPrint)
        {
            Wrapper<T> wrapper = new Wrapper<T>();
            wrapper.items = array;
            return JsonUtility.ToJson(wrapper, prettyPrint);
        }

        private class Wrapper<T>
        {
            public T[] items;
        }
    }



    void Start()
    {
        //先設置三個不同的陣列等一下給Turing使用
        List<string> equips_1 = new List<string>();
        equips_1.Add("sword");
        equips_1.Add("woman");
        equips_1.Add("fruit");

        List<string> equips_2 = new List<string>();
        equips_2.Add("shield");
        equips_2.Add("gun");
        equips_2.Add("child");


        List<string> equips_3 = new List<string>();
        equips_3.Add("sword");
        equips_3.Add("cannon");
        equips_3.Add("man");


        //設定每個數組的數量
        ArrayData[] playerInstance = new ArrayData[3];

        //設定每個數組的資料
        playerInstance[0] = new ArrayData();
        playerInstance[0].Health = 100;
        playerInstance[0].Money = 2000;
        playerInstance[0].Level = "Normal";
        playerInstance[0].Turing = equips_1;

        playerInstance[1] = new ArrayData();
        playerInstance[1].Health = 120;
        playerInstance[1].Money = 2000;
        playerInstance[1].Level = "Easy";
        playerInstance[1].Turing = equips_2;

        playerInstance[2] = new ArrayData();
        playerInstance[2].Health = 130;
        playerInstance[2].Money = 3200;
        playerInstance[2].Level = "Hard";
        playerInstance[2].Turing = equips_3;



        
       //將Json化的資料存進jsonInfo
        string jsonInfo = JsonHelper.ToJson(playerInstance, true);
        //輸出至本電腦File.WriteAllText("D:/20193DRowingVR/Mirro3DRowingUnity20194_ThirdPerson/Assets/file55699", jsonInfo);


        Debug.Log("寫入完成");
        Debug.Log(jsonInfo);

    }
}
輸出結果
JsonHelper讀取

using UnityEngine;
using System.IO;
using static JsonArrayDemo;
//繼承JsonArrayDemo中的JsonHelper
public class JsonHelperLoad : MonoBehaviour
{
    //宣告一個字串讀取檔案,宣告一個Data物件,來取得字串轉換後的物件
    string LoadData;
    public ArrayData[] player;
    void Start()
    {
        //讀取指定路徑的Json檔案並轉成字串
         LoadData = File.ReadAllText("D:/20193DRowingVR/Mirro3DRowingUnity20194_ThirdPerson/Assets/file55699");
        //將數組化ArrayJson反序列化並儲存至pplayer之中
         player = JsonHelper.FromJson<ArrayData>(LoadData);

        Debug.Log(player[0].Health);
        Debug.Log(player[1].Money);
    }
}
輸出結果


先這樣吧

其實還有一個JSONSimple的方式,已經搞定讀取的方法但是儲存還在摸索,過個幾天有時間再補上去
過幾天要去面試新的offer,希望可以順利。


創作回應

更多創作