關於快速的數據讀取和存儲——JSON(qwq)

從標題的小賣萌就可以看出來這篇是博主傾注了心血的愛的乾貨٩(๑❛ᴗ❛๑)۶

轉載請標明出處


囉囉嗦嗦的背景交代

這些天在寫交易系統的時候,需要用到很多物品,它們還是有分類的,不同的有不同的描述。自己第一個想到的就是定義一個物品類,在一個結構體裏把所有需要的屬性(類別、名字、描述、加成buff啥的)都放進去,大概又可以寫好多行了2333。這種方式也是我之前做過的方式,但這一次,博主多思考了一下,能不能把這些可修改的信息從代碼中抽離出來,作爲一個外部文件,以任何人都好理解和修改的方式存儲。博主再一想,emmmmm…外部文件,先想到的就是表格,txt存儲。再一想,這讀取的時候必然會涉及到字符串、空格什麼的處理的,博主覺得不夠明朗簡潔。就到網上去查閱了關於簡潔快速的unity中數據存儲的方式——JSON。 關於它,網上的博客教程都不盡相同,而且很亂。在這裏,我整合看過的知識,結合自己遇到的問題提出相應的講解方法,希望大家能夠有所收穫吧。


首先來介紹下,【摘自百度百科】

JSON(JavaScript Object Notation, JS 對象標記) 是一種輕量級的數據交換格式。它基於 ECMAScript (w3c制定的js規範)的一個子集,採用完全獨立於編程語言的文本格式來存儲和表示數據。簡潔和清晰的層次結構使得 JSON 成爲理想的數據交換語言。 易於人閱讀和編寫,同時也易於機器解析和生成,並有效地提升網絡傳輸效率。

很驚訝的是,它在遊戲服務器間的傳輸中已經算的是常用的處理方式了。好了,接下來進入正題:

1.JSON語法規則

•數據在鍵值對中

•數據由逗號分隔
•花括號保存對象
•方括號保存數組

2.JSON的結構

  • 對象:對象在js中表示爲“{}”括起來的內容,數據結構爲 {key:value,key:value,…}的鍵值對的結構,在面向對象的語言中,key爲對象的屬性,value爲對應的屬性值,所以很容易理解,取值方法爲 對象.key 獲取屬性值,這個屬性值的類型可以是 數字、字符串、數組、對象幾種。
  • 數組:數組在js中是中括號“[]”括起來的內容,數據結構爲 [“java”,”javascript”,”vb”,…],取值方式和所有語言中一樣,使用索引獲取,字段值的類型可以是 數字、字符串、數組、對象幾種。

3.JSON在unity中使用前的準備

  • JsonUtility:JsonUtility是Untiy5.3後新增的內容,有時會出現莫名其妙的錯誤:
    JsonUtility.FromJson():把json字符串轉成對象.
    JsonUtility.ToJson():把對象轉成json字符串.
  • LitJson:LitJson是一個Json的開源項目,這個比較穩定,推薦使用:
    JsonMapper.ToObject():把json字符串轉成對象.
    JsonMapper.ToJson():把對象轉成json字符串.
    戳這裏進官網下載,下載它的.dll文件就夠了傳送門
    然後把.dll文件放在你的項目的Assets裏,如圖
    這裏寫圖片描述
    使用的話要注意引入命名空間

以上,就完成了基本的瞭解和準備工作了。


結合代碼介紹

JSON採用完全獨立於語言的文本格式,但是也使用了類似於C語言家族的習慣(包括C, C++, C#, Java, JavaScript, Perl, Python等)。
Json創建中writer.WriteObjectStart ();就等同於“{”,writer.WriteObjectEnd ()就等同於“}”,最後要轉換成string型,json = writer.ToString ();。解析Json時,JsonData jsonData = JsonMapper.ToObject (json);注意複合Json解析完了是一個數組。

JsonData實現的接口如下:
IJsonWrapper, IList, ICollection, IEnumerable, IOrderedDictionary, IDictionary, IEquatable

string s = "[{'name':'lisi'},{'name':'zhangsan'}]";
string a = "{'name':'aaa'}";
JsonData[] jarr = JsonMapper.ToObject<JsonData[]>(s);
print(jarr. IsArray);//返回true
if(jarr.IsArray){
foreach(JsonData jd in jarr){
print(jd["name"]);//返回結果: lisi
// zhangsan
}
}
JsonData jdata = JsonMapper.ToObject(s);
print(jdata.IsArray);//返回true
if (jdata.IsArray)
{
for (int i = 0; i < jdata.Count;i ++ )
{
print(jdata[i]["name"]);//返回的結果: lisi
// zhangsan
}
}
JsonData j = JsonMapper.ToObject(a);
print(j.IsArray);//返回false
print(j["name"]);//返回aaa

從上面的示例可以看出JsonData是否能以數組的方式訪問需看json字符串返回的是否是數組類型的.對象內有一個數組.分別需要用到一個Json對象模型(JsonObjectModel)和一個Json數組模型(JsonArrayModel)來接收這兩種Json數據

示例展示了最基本得JsonData用法: 創建一個JsonData通常由JsonMapper的ToObject方法,這個方法有3個重載:
JsonMapper.ToObject(JsonReader reader);
JsonMapper.ToObject(string json);
JsonMapper.ToObject(System.IO.TextReader reader);

其中JsonReader類也是一個讀取json字串的類,不過它是按行的方式讀取,不能像key-value的方式讀取json的值,第二個是最常見的創建JsonData的方式,它只需提供一個json字串即可,第三個是讀取一個包含json字符的文本流來創建一個JsonData
JsonMapper中還有一個ToObject方法:public static T ToObject();當然它也有三個重載,同上


好了,現在也有了大致的瞭解,開始介紹使用流程啦。
首先,要書寫自己的外部文件【用來讀取和存儲的】,以.json格式

註明:就是在桌面上先新建一個記事本文檔,在另存爲修改爲所有文件後,把名字改成.json,如圖:
這裏寫圖片描述
保存成功後,就會是這樣色兒的——
這裏寫圖片描述
其中保存的數據格式是有點像枚舉類加數組的風格的,每個對象以 名字: 再以“{}”各自包裹着,之間以“,”隔開,最外層是“【】”
放一張其他博主的代碼圖片(其中涉及到了多個對象的情況 cards就是一個對象啦)
這裏寫圖片描述
而我寫的是沒有區分外面的大分別的,如下:【僅截取一部分】
這裏寫圖片描述
以上,就寫完了自己的外部json文件,接下來就是要按照一定的格式爲你的外部文件寫一個解析類!
解析類如下寫法:

public class Skill
 {
 public int id { set; get; }
 public string name { set; get; }
 public int damage { set; get; }

public override string ToString()
 {
 return string.Format("id:{0};name:{1};damage:{2}", id, name, damage);
 }
 }

博主放一下自己的解析類

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Text;

public class Item
{
    public int ID { get; set; }
    public string Name { get; set; }
    public ItemQuality Quality { get; set; }
    public ItemType Type { get; set; }
    public int Capacity { get; set; }//每一個格子中可存放物體的最大容量
    public string Description { get; set; }
    public int BuyPrice { get; set; }
    public int SellPrice { get; set; }
    public string Sprite { get; set; }//查找精靈路徑

    //物品類的構造函數
    public Item()
    {
        this.ID = -1;//表示這是一個空的物品類
    }
    public Item(int id, string name, ItemType type, ItemQuality quality, string description, int capaticy, int buyPrice, int sellPrice, string sprite)
    {
        this.ID = id;
        this.Name = name;
        this.Type = type;
        this.Quality = quality;
        this.Description = description;
        this.Capacity = capaticy;
        this.BuyPrice = buyPrice;
        this.SellPrice = sellPrice;
        this.Sprite = sprite;
    }

    //關於物品各個類型的詳細分類
    public enum ItemType
    {
        luxury,//奢飾品,包括的是各個地方的特產
        necessity//必需品,包括食物、木柴等生活用品
    }
    public enum ItemQuality
    {//同一類型物品之間按照質量指標來規定價錢
        Common,
        Rare,
        Legendary//傳奇的
    }

    //把類中的數據轉換爲字符串,在提示框中顯示
    public virtual string ToString()
    {

        string strItemType = "";
        switch (Type)
        {
            case ItemType.luxury:
                strItemType = "奢侈品";
                break;
            case ItemType.necessity:
                strItemType = "必需品";
                break;
        }
        string strItemQuality = "";
        switch (Quality)
        {
            case ItemQuality.Common:
                strItemQuality = "一般材質";
                break;
            case ItemQuality.Rare:
                strItemQuality = "稀有材質";
                break;
            case ItemQuality.Legendary:
                strItemQuality = "傳奇材質";
                break;
        }
        string color = ""; //用於設置提示框各個不同內容的顏色
        switch (Quality)
        {
            case ItemQuality.Common:
                color = "white";
                break;
            case ItemQuality.Rare:
                color = "yellow";
                break;
            case ItemQuality.Legendary:
                color = "blue";
                break;
        }
        string text = string.Format("<color={0}>{1}</color>\n<color=yellow><size=10>介紹:{2}</size></color>\n<color=red><size=12>容量:{3}</size></color>\n<color=green><size=12>物品類型:{4}</size></color>\n<color=blue><size=12>物品質量:{5}</size></color>\n<color=orange>購買價格$:{6}</color>\n<color=red>出售價格$:{7}</color>", color, Name, Description, Capacity, strItemType, strItemQuality, BuyPrice, SellPrice);
        return text;
    }


}

注意事項:解析的屬性必須與json中的屬性完全一致,否則無法獲取數據;此處爲了獲得輸出結果重寫tostring方法。

使用LitJson進行解析

//將解析的文本讀入一個字符串,如果是unity也是一樣
string str = File.ReadAllText(“Skill.Json”);
//要解析的是一個Skill類型的對象數組,使用泛型解析
Skill[] skillList = JsonMapper.ToObject

public class JsonDeserialize : MonoBehaviour
{  
    void Start( )
    {
         //獲取Json文件
        TextAsset jsonData = Resources.Load<TextAsset>("JsonData");

        JsonObjectModel jsonObject = JsonMapper.ToObject<JsonObjectModel>(jsonData.text);

        foreach (var info in  jsonObject.infoList)
        {
            Debug.Log(info.panelTypeString+" "+info.path);
        }

    }
}

本人偶然用到了JSONObject,如下

itemList = new List<Item>();
        //文本爲在Unity裏面是 TextAsset類型
        TextAsset itemText = Resources.Load<TextAsset>("message");
        string itemsJson = itemText.text;//物品信息的Json格式
        JSONObject j = new JSONObject(itemsJson);
        foreach (JSONObject temp in j.list)
        { ......}

第一次就出現了報錯,原因是JSONObject中沒有實現這些方法的代碼,所以你可以選擇自己寫來實現裏面存一個鏈表讀取數據什麼的,也可以去網上找開源的程序。

注意:當程序提醒你,json數據不能轉換爲什麼什麼數據的時候,大膽的強制轉換就好啦。

好了,博主的乾貨就到這裏啦,再分享幾個鏈接,講的真的好好,也是博主淘了好久找到的,希望可以助於理解啦。

開啓吧魔法陣1號ヾ(=・ω・=)o
開啓吧魔法陣2號٩(๑>◡<๑)۶

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章