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
}