using System; using System.Collections.Generic; using System.IO; using System.Linq; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using UnityEngine; using UnityEngine.Networking; namespace AibisDream.Utility { public static class JsonUtil { public const string JsonSuffix = ".json"; // 缓存的 JsonSerializerSettings,优化性能 private static readonly JsonSerializerSettings _defaultSettings = new JsonSerializerSettings { // 禁用类型名称处理,提升性能 TypeNameHandling = TypeNameHandling.None, // 使用默认的日期格式处理 DateFormatHandling = DateFormatHandling.IsoDateFormat, // 忽略循环引用 ReferenceLoopHandling = ReferenceLoopHandling.Ignore // 注意:不设置 NullValueHandling,保持默认行为(Include),避免改变现有功能 }; // 缓存的 JsonSerializer 实例,用于字典反序列化优化 private static readonly JsonSerializer _cachedSerializer = JsonSerializer.Create(_defaultSettings); /// /// 判断文件是否存在。Android 上 StreamingAssets 在 APK 内, 不可靠。 /// public static bool Exists(string filePath) { if (string.IsNullOrEmpty(filePath)) { return false; } #if UNITY_ANDROID && !UNITY_EDITOR if (filePath.Contains(Application.streamingAssetsPath)) { try { ReadFileText(filePath); return true; } catch (IOException) { return false; } } #endif return File.Exists(filePath); } /// /// 根据平台读取文件内容 /// private static string ReadFileText(string filePath) { #if UNITY_ANDROID && !UNITY_EDITOR // Android 平台需要使用 UnityWebRequest 读取 StreamingAssets if (filePath.Contains(Application.streamingAssetsPath)) { // Android 上 StreamingAssets 在 APK 中,需要构建正确的 URL string url = filePath; // 确保使用正确的路径分隔符 url = url.Replace("\\", "/"); // 如果路径不包含协议前缀,添加 file:// if (!url.StartsWith("file://") && !url.StartsWith("jar:file://")) { // 对于 Android APK 中的文件,使用 jar:file:// 协议 string relativePath = url.Replace(Application.streamingAssetsPath, "").TrimStart('/'); url = "jar:file://" + Application.dataPath + "!/assets/" + relativePath; } using (UnityWebRequest www = UnityWebRequest.Get(url)) { www.SendWebRequest(); // 等待请求完成(同步等待) while (!www.isDone) { // 在主线程中等待 } if (www.result == UnityWebRequest.Result.Success) { return www.downloadHandler.text; } else { throw new IOException($"无法读取文件: {filePath}, URL: {url}, 错误: {www.error}"); } } } else { // 非 StreamingAssets 路径,使用普通文件读取 return File.ReadAllText(filePath); } #else // 其他平台直接使用 File 类 return File.ReadAllText(filePath); #endif } /// /// 按路径和Key加载 /// /// 路径 /// key /// 类型 /// Bean /// 错误 public static T ReadBean(string path, string key) { string json = ReadFileText(path); JObject jObject = JObject.Parse(json); if (jObject.ContainsKey(key)) { return jObject.ToObject(); } throw new Exception("没有找到对应的Key"); } /// /// 按路径加载Json /// /// /// /// public static T ReadBean(string path) { string json = ReadFileText(path); return JsonConvert.DeserializeObject(json, _defaultSettings); } public static T ReadBeanByText(string text) { if (!text.StartsWith("{")) { text = "{" + text + "}"; } return JsonConvert.DeserializeObject(text, _defaultSettings); } /// /// 按路径加载Json /// /// 路径 /// Bean /// 目标Bean public static T[] ReadBeanArray(string path) { string json = ReadFileText(path); return JsonConvert.DeserializeObject(json, _defaultSettings); } /// /// 按路径加载Json /// /// 路径 /// Bean /// 目标Bean public static Dictionary ReadBeanDict(string path) { string json = ReadFileText(path); // 使用缓存的 JsonSerializerSettings 和 StringReader 优化性能 using (var reader = new StringReader(json)) using (var jsonReader = new JsonTextReader(reader)) { var result = _cachedSerializer.Deserialize>(jsonReader); return result; } } /// /// 获取Json中的Key列表 /// /// 路径 /// key列表 public static string[] ReadKeys(string path) { string json = ReadFileText(path); JObject jObject = JObject.Parse(json); return jObject.Properties().Select(jProp => jProp.Name).ToArray(); } public static JObject ReadJObject(string path) { string json = ReadFileText(FormatAsJsonPath(path)); return JObject.Parse(json); } /// /// 保存Bean /// /// bean /// 路径 /// 类型 public static void SaveBean(T bean, string path) { string json = JsonConvert.SerializeObject(bean); Directory.CreateDirectory(Path.GetDirectoryName(path)); File.WriteAllText(path, json); } public static void SaveJObject(JObject jObject, string path) { string json = jObject.ToString(); Directory.CreateDirectory(Path.GetDirectoryName(path)); File.WriteAllText(FormatAsJsonPath(path), json); } public static void SaveArray(T[] array, string path) { string json = JsonConvert.SerializeObject(array); Directory.CreateDirectory(Path.GetDirectoryName(path)); File.WriteAllText(FormatAsJsonPath(path), json); } /// /// 保存类 /// /// 对象 /// key /// 保存配置 /// 添加还是覆盖 /// 类型 public static void SaveBean(T bean, string key, string path, SaveMode saveMode = SaveMode.Add) { if (saveMode == SaveMode.Add && File.Exists(path)) { Dictionary originDic = JsonConvert.DeserializeObject>(path); originDic.Add(key, bean); string tempJson = JsonConvert.SerializeObject(originDic); File.WriteAllText(path, tempJson); } else { Dictionary tempDic = new Dictionary { { key, bean } }; string tempJson = JsonConvert.SerializeObject(tempDic); File.WriteAllText(path, tempJson); } } /// /// 自动把文件名转为Json /// /// 文件名 /// 已改为json的文件名 public static string FormatAsJsonPath(string fileName) { if (!fileName.EndsWith(JsonSuffix)) { return fileName + JsonSuffix; } return fileName; } } public enum SaveMode { Replace, Add } }