HuldaGnodim 发表于 2023-3-5 11:52

Unity中使用JSON实现数据读写

由于某些原因需要将数据保存在本地,并且在某些时候进行编辑并加载,比如保存场景信息,保存游戏状态,保存运行时获得的数据等。
常规的方法有XML,二进制和JSON,前两个不需要通过第三方库实现,缺点是相对繁琐。JSON的好处是数据轻量,过程简单,这次遇到数据保存的需求时,尝试了这三种方法,最终选择了JSON。
导入JSON库

这里使用的是同事推荐的JSON.cs,下载地址。
代码中添加命名空间

using MiniJSON2;
JSON库的使用

public JSON(object jsonKey , object jsonValue)
{
        fields.Add(jsonKey.ToString(),jsonValue);
}
JSON数据库的一个关键API是JSON(object Key ,object Value),它类似Dictionary<key,value>类型,使用方法是将Value与某一个key一一对应。
导出JSON到文件

为了换装,使用的数据结构是Dictionary<string name, Dictionary<int currentNum, string path>>,从效果上来说就是希望通过换装部位名称加一个数字,就能得到应有资源的地址,从而用Resources.Load或者www来加载资源。接下来就是思考如何将他们转成JSON数据,开始还想着既然有三个变量,那我应该用三个数据来保存以便以后加载时组合吧,但……嗯想想也是挺傻的,估计是最近感冒了(一定是这样 (▽`) )。
private void SetJsonData(ref JSON resJson, string key)
{
        List<string> res_man = new List<string>();

        if (avatarData._avatarResData.ContainsKey(key))        //判断key是否存在
        {
                foreach (KeyValuePair<int, strin> i in avatarData._avatarResData)
                {
                        res_man.Add(i.Value);
                }
                resJson = res_man.ToArray();
        }
        else
                Debug.Log(key + "key is none");

        Debug.Log(key + " is done=================");
}
这里的avatarData._avatarResData就是之前定义的字典数据,通过遍历avatarData._avatarResData这个字典数据,得到某个key的所有路径数组数据并保存在临时变量res_man里,之后通过resJson = res_man.ToArray();将res_man里的数据赋值给resJson,这样得到的JSON数据里即有了也有了与之对应的(数组型value)。接下来需要将处理好的JSON数据保存到本地。
首先需要添加文件处理的命名空间,
using System.IO;
然后添加将JSON数据保存到本地的方法:
void SaveJsonToFile(JSON json)
{
        File.WriteAllText(Application.dataPath + "/Resources/_avatarResDataForMobile.json",
        json.serialized,
        System.Text.Encoding.UTF8);
}
这里用到JSON.serialized方法,其目的是将JSON数据序列化,进而使用Encoding.UTF8的方式保存数据。保存的格式可以是txt或者json。
读取JSON文件

首先添加获取本地文件的方法,因为之前我将文件保存在Resources文件夹下,因此获取地址也是写死的(不建议)。
void LoadJsonFromFile(ref JSON json)
{
        TextAsset txt = Resources.Load("_avatarResDataForMobile") as TextAsset;
        json.serialized = txt.text;
}
然后创建LoadAvatarData()进行调用。
public void LoadAvatarData()
{
        JSON resJson = new JSON();
        LoadJsonFromFile(ref resJson);
}
经过以上两步操作,获取的JSON数据就被保存在resJson之中。
使用JSON接口还原数据

以上已经获取到JSON数据,再将数据还原也不难,直接上代码。
public void LoadAvatarData()
{
        JSON resJson = new JSON();
        LoadJsonFromFile(ref resJson);
        GetJsonData(ref resJson, "tshirt");//将JSON数据还原成源数据
}

private void GetJsonData(ref JSON resJson,string key)
{
        string[] res_man = resJson.ToArray<string>(key);

        int t = 0;

        if (!AvatarResourceData._avatarResDataForMobile.ContainsKey(key)) //判断key是否存在
                AvatarResourceData._avatarResDataForMobile.Add(key, new Dictionary<int, string>());

        foreach (string s in res_man)
        {
                t++;
                AvatarResourceData._avatarResDataForMobile.Add(t, s);
        }
}
这里需要注意的是AvatarResourceData._avatarResDataForMobile这个变量是我在其他地方定义的全局变量,类型和上文提到的_avatarResData一样,由于某些原因需要这样(懒)。
public Dictionary<string, Dictionary<int, string>> _avatarResData = new Dictionary<string, Dictionary<int, string>>();
public static Dictionary<string, Dictionary<int, string>> _avatarResDataForMobile = new Dictionary<string, Dictionary<int, string>>();总结

使用JSON库的关键是
JSON(object Key ,object Value)
这可以定义任意类型key与任意类型value的绑定,实现各种格式的保存及加载。
附完整代码,供参考(由于文章需要,上文中的部分代码做了简化,以便理解)。对了,这里还有种数据保存方式:PlayerPrefs.SetString(string key, string value),和字典类型类似,可以将value保存在本地某处,缺点是这个路径安卓端获取不到,因此作罢。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MiniJSON2;
using System.IO;

public class ReadWriteAvatarRes : MonoBehaviour {
        public AvatarResourceData avatarData;

        private void Start()
        {
                if (Resources.Load("_avatarResDataForMobile") == null)
                        SaveAvatarData();

                LoadAvatarData();
        }

        public void SaveAvatarData()
        {
                JSON resJson = new JSON();

                SetJsonData(ref resJson,"tshirt");
                SetJsonData(ref resJson,"hair");
                SetJsonData(ref resJson,"hat");
                SetJsonData(ref resJson, "pants");
                SetJsonData(ref resJson, "shoes");
                SetJsonData(ref resJson,"glasses");
                SetJsonData(ref resJson,"headset");
                SetJsonData(ref resJson,"mask");
                SetJsonData(ref resJson, "jacket");

                SetJsonData(ref resJson, "face");
                SetJsonData(ref resJson, "eyebow");
                SetJsonData(ref resJson,"lip");
                SetJsonData(ref resJson, "eye");

                //PlayerPrefs.SetString("_avatarResDataForMobile", resJson.serialized);
                SaveJsonToFile(resJson);
        }

        private void SetJsonData(ref JSON resJson, string key)
        {
                List<string> res_man = new List<string>();
                List<string> res_girl = new List<string>();

                if (avatarData._avatarResData.ContainsKey("G_" + key))        //判断key是否存在
                {
                        foreach (KeyValuePair<int, string> i in avatarData._avatarResData["G_" + key])
                        {
                                res_girl.Add(i.Value);
                        }
                        resJson["G_" + key] = res_girl.ToArray();
                }
                else
                        Debug.Log(key + "type is none G_");

                if(avatarData._avatarResData.ContainsKey("M_" + key))
                {
                        foreach (KeyValuePair<int, string> i in avatarData._avatarResData["M_" + key])
                        {
                                res_man.Add(i.Value);
                        }
                        resJson["M_" + key] = res_man.ToArray();
                }
                else
                        Debug.Log(key + "type is none");

                Debug.Log(key + " is done=================");
        }

        public void LoadAvatarData()
        {
                JSON resJson = new JSON();

                //resJson.serialized = PlayerPrefs.GetString("_avatarResDataForMobile");
                LoadJsonFromFile(ref resJson);

                GetJsonData(ref resJson, "tshirt");
                GetJsonData(ref resJson, "hair");
                GetJsonData(ref resJson, "hat");
                GetJsonData(ref resJson, "pants");
                GetJsonData(ref resJson, "shoes");
                GetJsonData(ref resJson, "glasses");
                GetJsonData(ref resJson, "headset");
                GetJsonData(ref resJson, "jacket");
                GetJsonData(ref resJson, "mask");

                GetJsonData(ref resJson, "face");
                GetJsonData(ref resJson, "eyebow");
                GetJsonData(ref resJson, "lip");
                GetJsonData(ref resJson, "eye");
        }

        private void GetJsonData(ref JSON resJson,string key)
        {
                string[] res_girl = resJson.ToArray<string>("G_" + key);
                string[] res_man = resJson.ToArray<string>("M_" + key);

                int i = 0;
                int t = 0;

                if (!AvatarResourceData._avatarResDataForMobile.ContainsKey("G_"+ key))
                        AvatarResourceData._avatarResDataForMobile.Add("G_"+ key, new Dictionary<int, string>());
                if (!AvatarResourceData._avatarResDataForMobile.ContainsKey("M_" + key))
                        AvatarResourceData._avatarResDataForMobile.Add("M_" + key, new Dictionary<int, string>());

                foreach (string s in res_girl)
                {
                        i++;
                        AvatarResourceData._avatarResDataForMobile["G_" + key].Add(i, s);
                }
                foreach (string s in res_man)
                {
                        t++;
                        AvatarResourceData._avatarResDataForMobile["M_" + key].Add(t, s);
                }
        }

        void LoadJsonFromFile(ref JSON json)
        {
                TextAsset txt = Resources.Load("_avatarResDataForMobile") as TextAsset;
                json.serialized = txt.text;
        }
        void SaveJsonToFile(JSON json)
        {
                File.WriteAllText(Application.dataPath + "/Resources/_avatarResDataForMobile.json", json.serialized, System.Text.Encoding.UTF8);
        }
页: [1]
查看完整版本: Unity中使用JSON实现数据读写