using System.Text.Json; namespace Yi.Framework.AiHub.Domain.Shared.Extensions; public static class JsonElementExtensions { #region 路径访问 /// /// 链式获取深层属性,支持对象属性和数组索引 /// /// /// root.GetPath("user", "addresses", 0, "city") /// public static JsonElement? GetPath(this JsonElement element, params object[] path) { JsonElement current = element; foreach (var key in path) { switch (key) { case string propertyName: if (current.ValueKind != JsonValueKind.Object || !current.TryGetProperty(propertyName, out current)) return null; break; case int index: if (current.ValueKind != JsonValueKind.Array || index < 0 || index >= current.GetArrayLength()) return null; current = current[index]; break; default: return null; } } return current; } /// /// 安全获取对象属性 /// public static JsonElement? Get(this JsonElement element, string propertyName) { if (element.ValueKind == JsonValueKind.Object && element.TryGetProperty(propertyName, out var value)) return value; return null; } /// /// 安全获取数组元素 /// public static JsonElement? Get(this JsonElement element, int index) { if (element.ValueKind == JsonValueKind.Array && index >= 0 && index < element.GetArrayLength()) return element[index]; return null; } /// /// 链式安全获取对象属性 /// public static JsonElement? Get(this JsonElement? element, string propertyName) => element?.Get(propertyName); /// /// 链式安全获取数组元素 /// public static JsonElement? Get(this JsonElement? element, int index) => element?.Get(index); #endregion #region 取值方法(带默认值) public static string? GetString(this JsonElement? element, string? defaultValue = null) => element?.ValueKind == JsonValueKind.String ? element.Value.GetString() : defaultValue; public static int GetInt(this JsonElement? element, int defaultValue = 0) => element?.ValueKind == JsonValueKind.Number ? element.Value.GetInt32() : defaultValue; public static long GetLong(this JsonElement? element, long defaultValue = 0) => element?.ValueKind == JsonValueKind.Number ? element.Value.GetInt64() : defaultValue; public static double GetDouble(this JsonElement? element, double defaultValue = 0) => element?.ValueKind == JsonValueKind.Number ? element.Value.GetDouble() : defaultValue; public static decimal GetDecimal(this JsonElement? element, decimal defaultValue = 0) => element?.ValueKind == JsonValueKind.Number ? element.Value.GetDecimal() : defaultValue; public static bool GetBool(this JsonElement? element, bool defaultValue = false) => element?.ValueKind is JsonValueKind.True or JsonValueKind.False ? element.Value.GetBoolean() : defaultValue; public static DateTime GetDateTime(this JsonElement? element, DateTime defaultValue = default) => element?.ValueKind == JsonValueKind.String && element.Value.TryGetDateTime(out var dt) ? dt : defaultValue; public static Guid GetGuid(this JsonElement? element, Guid defaultValue = default) => element?.ValueKind == JsonValueKind.String && element.Value.TryGetGuid(out var guid) ? guid : defaultValue; #endregion #region 可空取值方法 public static int? GetIntOrNull(this JsonElement? element) => element?.ValueKind == JsonValueKind.Number ? element.Value.GetInt32() : null; public static long? GetLongOrNull(this JsonElement? element) => element?.ValueKind == JsonValueKind.Number ? element.Value.GetInt64() : null; public static double? GetDoubleOrNull(this JsonElement? element) => element?.ValueKind == JsonValueKind.Number ? element.Value.GetDouble() : null; public static decimal? GetDecimalOrNull(this JsonElement? element) => element?.ValueKind == JsonValueKind.Number ? element.Value.GetDecimal() : null; public static bool? GetBoolOrNull(this JsonElement? element) => element?.ValueKind is JsonValueKind.True or JsonValueKind.False ? element.Value.GetBoolean() : null; public static DateTime? GetDateTimeOrNull(this JsonElement? element) => element?.ValueKind == JsonValueKind.String && element.Value.TryGetDateTime(out var dt) ? dt : null; public static Guid? GetGuidOrNull(this JsonElement? element) => element?.ValueKind == JsonValueKind.String && element.Value.TryGetGuid(out var guid) ? guid : null; #endregion #region 数组操作 /// /// 安全获取数组,不存在返回空数组 /// public static IEnumerable GetArray(this JsonElement? element) { if (element?.ValueKind == JsonValueKind.Array) { foreach (var item in element.Value.EnumerateArray()) yield return item; } } /// /// 获取数组长度 /// public static int GetArrayLength(this JsonElement? element) => element?.ValueKind == JsonValueKind.Array ? element.Value.GetArrayLength() : 0; /// /// 数组转 List /// public static List ToStringList(this JsonElement? element) => element.GetArray().Select(e => e.GetString()).ToList(); public static List ToIntList(this JsonElement? element) => element.GetArray() .Where(e => e.ValueKind == JsonValueKind.Number) .Select(e => e.GetInt32()) .ToList(); #endregion #region 对象操作 /// /// 安全枚举对象属性 /// public static IEnumerable GetProperties(this JsonElement? element) { if (element?.ValueKind == JsonValueKind.Object) { foreach (var prop in element.Value.EnumerateObject()) yield return prop; } } /// /// 获取所有属性名 /// public static IEnumerable GetPropertyNames(this JsonElement? element) => element.GetProperties().Select(p => p.Name); /// /// 判断是否包含某属性 /// public static bool HasProperty(this JsonElement? element, string propertyName) => element?.ValueKind == JsonValueKind.Object && element.Value.TryGetProperty(propertyName, out _); #endregion #region 类型判断 public static bool IsNull(this JsonElement? element) => element == null || element.Value.ValueKind == JsonValueKind.Null; public static bool IsNullOrUndefined(this JsonElement? element) => element == null || element.Value.ValueKind is JsonValueKind.Null or JsonValueKind.Undefined; public static bool IsObject(this JsonElement? element) => element?.ValueKind == JsonValueKind.Object; public static bool IsArray(this JsonElement? element) => element?.ValueKind == JsonValueKind.Array; public static bool IsString(this JsonElement? element) => element?.ValueKind == JsonValueKind.String; public static bool IsNumber(this JsonElement? element) => element?.ValueKind == JsonValueKind.Number; public static bool IsBool(this JsonElement? element) => element?.ValueKind is JsonValueKind.True or JsonValueKind.False; public static bool Exists(this JsonElement? element) => element != null && element.Value.ValueKind != JsonValueKind.Undefined; #endregion #region 反序列化 /// /// 反序列化为指定类型 /// public static T? Deserialize(this JsonElement? element, JsonSerializerOptions? options = null) => element.HasValue ? element.Value.Deserialize(options) : default; /// /// 反序列化为指定类型,带默认值 /// public static T Deserialize(this JsonElement? element, T defaultValue, JsonSerializerOptions? options = null) => element.HasValue ? element.Value.Deserialize(options) ?? defaultValue : defaultValue; #endregion #region 转换为字典/动态类型 /// /// 转换为 Dictionary /// public static Dictionary? ToDictionary(this JsonElement? element) { if (element?.ValueKind != JsonValueKind.Object) return null; var dict = new Dictionary(); foreach (var prop in element.Value.EnumerateObject()) dict[prop.Name] = prop.Value; return dict; } #endregion #region 原始值 /// /// 获取原始 JSON 字符串 /// public static string? GetRawText(this JsonElement? element) => element?.GetRawText(); #endregion }