從標題的小賣萌就可以看出來這篇是博主傾注了心血的愛的乾貨٩(๑❛ᴗ❛๑)۶
轉載請標明出處
囉囉嗦嗦的背景交代
這些天在寫交易系統的時候,需要用到很多物品,它們還是有分類的,不同的有不同的描述。自己第一個想到的就是定義一個物品類,在一個結構體裏把所有需要的屬性(類別、名字、描述、加成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數據不能轉換爲什麼什麼數據的時候,大膽的強制轉換就好啦。
好了,博主的乾貨就到這裏啦,再分享幾個鏈接,講的真的好好,也是博主淘了好久找到的,希望可以助於理解啦。