<unity>关于快速的数据读取和存储——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号٩(๑>◡<๑)۶

猜你喜欢

转载自blog.csdn.net/zys91011_muse/article/details/76282770