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
}
}