Unity数据持久化之Json

1、Json是什么

JSON是一种取代XML的数据结构。
和xml相比,它更小巧但描述能力却不差,由于它的小巧所以网络传输数据将减少更多流量从而加快速度。

Unity数据持久化之Json_第1张图片

2、将对象转化成Json

原对象:
Unity数据持久化之Json_第2张图片
转成Json后
Unity数据持久化之Json_第3张图片

3、Excel转化成Json

Unity数据持久化之Json_第4张图片
这样写到excel中,然后复制excel中的内容到网站上,例如https://www.bejson.com/json/col2json/ 这个地方,直接就可以转成想要的Json文件,该方法比较笨,正确做法是应该有个自动化工具帮忙完成这一系列操作,日后编辑器开发在搞。等待补充········

4、JsonUtility的使用

4.1 作用

 JsonUtlity 是Unity自带的用于解析Json的公共类
 1.将内存中对象序列化为Json格式的字符串
 2.将Json字符串反序列化为类对象

4.2 特点

   注意:
    1.float序列化时看起来会有一些误差
    2.自定义类需要加上序列化特性[System.Serializable]
    3.想要序列化私有变量 需要加上特性[SerializeField]
    4.JsonUtility不支持字典
    5.JsonUtlity存储null对象不会是null 而是默认值的数据 ,例如int类型的就是0

4.3 代码

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

[System.Serializable]
public class Student
{
    public int age;
    public string name;

    public Student(int age, string name)
    {
        this.age = age;
        this.name = name;
    }
}
/// 
/// 这个不用加序列化是因为它是被直接进行序列化的,属于第一层,但是内部的Student就需要特别处理下了
/// 
public class MrTang
{
    public string name;
    public int age;
    public bool sex;
    public float testF;
    public double testD;

    public int[] ids;
    public List ids2;
    public Dictionary dic;
    public Dictionary dic2;

    public Student s1;
    public List s2s;
    //除了public类型之外的都需要加这个才会被序列化
    [SerializeField]
    private int privateI = 1;
    [SerializeField]
    protected int protectedI = 2;
}

public class RoleData
{
    public List list;
}
//如果这个类不是在Json直接转化的第一层对象,是对象内的对象,那么就需要加一个这个,不然不会被序列化
[System.Serializable]
public class RoleInfo
{
    public int hp;
    public int speed;
    public int volume;
    public string resName;
    public int scale;
}

public class JsonManager : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        #region 知识点一 JsonUtlity是什么?
        //JsonUtlity 是Unity自带的用于解析Json的公共类
        //它可以
        //1.将内存中对象序列化为Json格式的字符串
        //2.将Json字符串反序列化为类对象
        #endregion

        #region 知识点二 必备知识点——在文件中存读字符串
        //1.存储字符串到指定路径文件中
        //第一个参数 填写的是 存储的路径
        //第二个参数 填写的是 存储的字符串内容
        //注意:第一个参数 必须是存在的文件路径 如果没有对应文件夹 会报错
        File.WriteAllText(Application.persistentDataPath + "/Test.json", "唐老狮存储的json文件");
        print(Application.persistentDataPath);

        //2.在指定路径文件中读取字符串
        string str = File.ReadAllText(Application.persistentDataPath + "/Test.json");
        print(str);
        #endregion

        #region 知识点三 使用JsonUtlity进行序列化
        //序列化:把内存中的数据 存储到硬盘上
        //方法:
        //JsonUtility.ToJson(对象)
        MrTang t = new MrTang();
        t.name = "唐老狮";
        t.age = 18;
        t.sex = false;
        t.testF = 1.4f;
        t.testD = 1.4;

        t.ids = new int[] { 1, 2, 3, 4 };
        t.ids2 = new List() { 1, 2, 3 };
        t.dic = new Dictionary() { { 1, "123" }, { 2, "234" } };
        t.dic2 = new Dictionary() { { "1", "123" }, { "2", "234" } };

        t.s1 = null;//new Student(1, "小红");
        t.s2s = new List() { new Student(2, "小明"), new Student(3, "小强") };

        //Jsonutility提供了线程的方法 可以把类对象 序列化为 json字符串
        string jsonStr = JsonUtility.ToJson(t);
        File.WriteAllText(Application.persistentDataPath + "/MrTang.json", jsonStr);

  
        #endregion

        #region 知识点四 使用JsonUtlity进行反序列化
        //反序列化:把硬盘上的数据 读取到内存中
        //方法:
        //JsonUtility.FromJson(字符串)
        //读取文件中的 Json字符串
        jsonStr = File.ReadAllText(Application.persistentDataPath + "/MrTang.json");
        //使用Json字符串内容 转换成类对象
        MrTang t2 = JsonUtility.FromJson(jsonStr, typeof(MrTang)) as MrTang;
        MrTang t3 = JsonUtility.FromJson(jsonStr);

        //注意:
        //如果Json中数据少了,读取到内存中类对象中时不会报错
        #endregion

        #region 知识点五 注意事项
        //1.JsonUtlity无法直接读取数据集合,如果json中是以[]开始的,那么就会报错,必须要在多裹一层,想要解决就需要下面那种方法,在代码内多套一层
        jsonStr = File.ReadAllText(Application.streamingAssetsPath + "/RoleInfo2.json");
        print(jsonStr);
        //List roleInfoList = JsonUtility.FromJson>(jsonStr);
        RoleData data = JsonUtility.FromJson(jsonStr);

        //2.文本编码格式需要时UTF-8 不然无法加载
        #endregion

        #region 总结
        //1.必备知识点 —— File存读字符串的方法 ReadAllText和WriteAllText
        //2.JsonUtlity提供的序列化反序列化方法 ToJson 和 FromJson
        //3.自定义类需要加上序列化特性[System.Serializable]
        //4.私有保护成员 需要加上[SerializeField]
        //5.JsonUtlity不支持字典
        //6.JsonUtlity不能直接将数据反序列化为数据集合
        //7.Json文档编码格式必须是UTF-8
        #endregion
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

5、LitJson的使用

4.1 作用

  它是一个第三方库,用于处理Json的序列化和反序列化
    LitJson是C#编写的,体积小、速度快、易于使用
    它可以很容易的嵌入到我们的代码中
    只需要将LitJson代码拷贝到工程中即可
    //1.前往LitJson官网
    //2.通过官网前往GitHub获取最新版本代码
    //3.将代码(src里面的那个即如下图,多余的删除即可)拷贝到Unity工程中 即可开始使用LitJson

Unity数据持久化之Json_第5张图片

4.2 特点

    LitJson注意:
    1.相对JsonUtlity不需要加特性,对于类也不需要加
    2.不能序列化私有变量
    3.支持字典类型,字典的键 建议都是字符串(将key是int转成string存) 因为 Json的特点 Json中的键会加上双引号,
    不然反序列化的时候会出
    4.需要引用LitJson命名空间
    5.LitJson可以准确的保存null类型

4.3 代码


存进去XMl会有乱码的情况,不用管,反序列化就是正常的

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

public class Student2
{
    public int age;
    public string name;

    public Student2() { }

    public Student2(int age, string name)
    {
        this.age = age;
        this.name = name;
    }
}

public class MrTang2
{
    public string name;
    public int age;
    public bool sex;
    public float testF;
    public double testD;

    public int[] ids;
    public List ids2;
    //public Dictionary dic;
    public Dictionary dic2;

    public Student2 s1;
    public List s2s;

    private int privateI = 1;
    protected int protectedI = 2;
}

public class RoleInfo2
{
    public int hp;
    public int speed;
    public int volume;
    public string resName;
    public int scale;
}

public class LitJsonTest : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        #region 知识点一 LitJson是什么?
        //它是一个第三方库,用于处理Json的序列化和反序列化
        //LitJson是C#编写的,体积小、速度快、易于使用
        //它可以很容易的嵌入到我们的代码中
        //只需要将LitJson代码拷贝到工程中即可
        #endregion

        #region 知识点二 获取LitJson
        //1.前往LitJson官网
        //2.通过官网前往GitHub获取最新版本代码
        //3.讲代码拷贝到Unity工程中 即可开始使用LitJson
        #endregion

        #region 知识点三 使用LitJson进行序列化
        //方法:
        //JsonMapper.ToJson(对象)
        MrTang2 t = new MrTang2();
        t.name = "唐老狮";
        t.age = 18;
        t.sex = true;
        t.testF = 1.4f;
        t.testD = 1.4;

        t.ids = new int[] { 1, 2, 3, 4 };
        t.ids2 = new List() { 1, 2, 3 };
        //t.dic = new Dictionary() { { 1, "123" }, { 2, "234" } };
        t.dic2 = new Dictionary() { { "1", "123" }, { "2", "234" } };

        t.s1 = null;//new Student(1, "小红");
        t.s2s = new List() { new Student2(2, "小明"), new Student2(3, "小强") };

        string jsonStr = JsonMapper.ToJson(t);
        print(Application.persistentDataPath);
        File.WriteAllText(Application.persistentDataPath + "/MrTang2.json", jsonStr);

        //注意:
        //1.相对JsonUtlity不需要加特性
        //2.不能序列化私有变量
        //3.支持字典类型,字典的键 建议都是字符串 因为 Json的特点 Json中的键会加上双引号
        //4.需要引用LitJson命名空间
        //5.LitJson可以准确的保存null类型
        #endregion

        #region 知识点四 使用LitJson反序列化
        //方法:
        //JsonMapper.ToObject(字符串)
        jsonStr = File.ReadAllText(Application.persistentDataPath + "/MrTang2.json");
        //JsonData是LitJson提供的类对象 可以用键值对的形式去访问其中的内容
        JsonData data = JsonMapper.ToObject(jsonStr);
        print(data["name"]);
        print(data["age"]);
        //通过泛型转换 更加的方便 建议使用这种方式
        MrTang2 t2 = JsonMapper.ToObject(jsonStr);
        print(t2.name);
        print(t2.age);
        //注意:
        //1.类结构需要无参构造函数,否则反序列化时报错
        //2.字典虽然支持 但是键在使用为数值时会有问题 需要使用字符串类型
        #endregion

        #region 知识点五 注意事项
        //1.LitJson可以直接读取数据集合
        // jsonStr = File.ReadAllText(Application.streamingAssetsPath + "/RoleInfo.json");
        jsonStr = File.ReadAllText(Application.persistentDataPath + "/RoleInfo2.json");
        print(jsonStr);
        RoleInfo2[] arr = JsonMapper.ToObject(jsonStr);
        print(arr[0].hp);
        // 这个需要在json外层
        List list = JsonMapper.ToObject>(jsonStr);

        // jsonStr = File.ReadAllText(Application.streamingAssetsPath + "/Dic.json");
        // Dictionary dicTest = JsonMapper.ToObject>(jsonStr);

        //2.文本编码格式需要是UTF-8 不然无法加载
        #endregion

        #region 总结
        //1.LitJson提供的序列化反序列化方法 JsonMapper.ToJson和ToObject<>
        //2.LitJson无需加特性
        //3.LitJson不支持私有变量
        //4.LitJson支持字典序列化反序列化
        //5.LitJson可以直接将数据反序列化为数据集合
        //6.LitJson反序列化时 自定义类型需要无参构造
        //7.Json文档编码格式必须是UTF-8
        #endregion
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

– json文件

{
	"list":[
	{"hp":4,"speed":6,"volume":5,"resName":"Airplane/Airplane1","scale":15},
	{"hp":3,"speed":7,"volume":4,"resName":"Airplane/Airplane2","scale":15},
	{"hp":2,"speed":8,"volume":3,"resName":"Airplane/Airplane3","scale":15},
	{"hp":10,"speed":3,"volume":10,"resName":"Airplane/Airplane4","scale":6},
	{"hp":6,"speed":5,"volume":7,"resName":"Airplane/Airplane5","scale":10}
	]
}

6、两者的区别

6.1 相同点

  • 他们都是用于Json的序列化反序列化
  • Json文档编码格式必须是UTF-8
  • 都是通过静态类进行方法调用

6.2不同点

  • JsonUtlity是Unity自带,LitJson是第三方需要引用命名空间
  • JsonUtlity使用时自定义类需要加特性,LitJson不需要
  • JsonUtlity支持私有变量(加特性),LitJson不支持
  • JsonUtlity不支持字典,LitJson支持(但是键只能是字符串)
  • JsonUtlity不能直接将数据反序列化为数据集合(数组字典),LitJson可以
  • JsonUtlity对自定义类不要求有无参构造,LitJson需要
  • JsonUtlity存储空对象时会存储默认值而不是null,LitJson会存null

6.3 如何选择

根据实际需求
建议使用LitJson
原因:LitJson不用加特性,支持字典,支持直接反序列化为数据集合,存储null更准确

你可能感兴趣的:(C#,unity,json,unity,C#)