279 lines
9.3 KiB
C#
279 lines
9.3 KiB
C#
using System.Text.Json;
|
||
|
||
namespace Yi.Framework.AiHub.Domain.Shared.Extensions;
|
||
|
||
public static class JsonElementExtensions
|
||
{
|
||
#region 路径访问
|
||
|
||
/// <summary>
|
||
/// 链式获取深层属性,支持对象属性和数组索引
|
||
/// </summary>
|
||
/// <example>
|
||
/// root.GetPath("user", "addresses", 0, "city")
|
||
/// </example>
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 安全获取对象属性
|
||
/// </summary>
|
||
public static JsonElement? Get(this JsonElement element, string propertyName)
|
||
{
|
||
if (element.ValueKind == JsonValueKind.Object &&
|
||
element.TryGetProperty(propertyName, out var value))
|
||
return value;
|
||
return null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 安全获取数组元素
|
||
/// </summary>
|
||
public static JsonElement? Get(this JsonElement element, int index)
|
||
{
|
||
if (element.ValueKind == JsonValueKind.Array &&
|
||
index >= 0 && index < element.GetArrayLength())
|
||
return element[index];
|
||
return null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 链式安全获取对象属性
|
||
/// </summary>
|
||
public static JsonElement? Get(this JsonElement? element, string propertyName)
|
||
=> element?.Get(propertyName);
|
||
|
||
/// <summary>
|
||
/// 链式安全获取数组元素
|
||
/// </summary>
|
||
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 数组操作
|
||
|
||
/// <summary>
|
||
/// 安全获取数组,不存在返回空数组
|
||
/// </summary>
|
||
public static IEnumerable<JsonElement> GetArray(this JsonElement? element)
|
||
{
|
||
if (element?.ValueKind == JsonValueKind.Array)
|
||
{
|
||
foreach (var item in element.Value.EnumerateArray())
|
||
yield return item;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取数组长度
|
||
/// </summary>
|
||
public static int GetArrayLength(this JsonElement? element)
|
||
=> element?.ValueKind == JsonValueKind.Array ? element.Value.GetArrayLength() : 0;
|
||
|
||
/// <summary>
|
||
/// 数组转 List
|
||
/// </summary>
|
||
public static List<string?> ToStringList(this JsonElement? element)
|
||
=> element.GetArray().Select(e => e.GetString()).ToList();
|
||
|
||
public static List<int> ToIntList(this JsonElement? element)
|
||
=> element.GetArray()
|
||
.Where(e => e.ValueKind == JsonValueKind.Number)
|
||
.Select(e => e.GetInt32())
|
||
.ToList();
|
||
|
||
#endregion
|
||
|
||
#region 对象操作
|
||
|
||
/// <summary>
|
||
/// 安全枚举对象属性
|
||
/// </summary>
|
||
public static IEnumerable<JsonProperty> GetProperties(this JsonElement? element)
|
||
{
|
||
if (element?.ValueKind == JsonValueKind.Object)
|
||
{
|
||
foreach (var prop in element.Value.EnumerateObject())
|
||
yield return prop;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取所有属性名
|
||
/// </summary>
|
||
public static IEnumerable<string> GetPropertyNames(this JsonElement? element)
|
||
=> element.GetProperties().Select(p => p.Name);
|
||
|
||
/// <summary>
|
||
/// 判断是否包含某属性
|
||
/// </summary>
|
||
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 反序列化
|
||
|
||
/// <summary>
|
||
/// 反序列化为指定类型
|
||
/// </summary>
|
||
public static T? Deserialize<T>(this JsonElement? element, JsonSerializerOptions? options = null)
|
||
=> element.HasValue ? element.Value.Deserialize<T>(options) : default;
|
||
|
||
/// <summary>
|
||
/// 反序列化为指定类型,带默认值
|
||
/// </summary>
|
||
public static T Deserialize<T>(this JsonElement? element, T defaultValue, JsonSerializerOptions? options = null)
|
||
=> element.HasValue ? element.Value.Deserialize<T>(options) ?? defaultValue : defaultValue;
|
||
|
||
#endregion
|
||
|
||
#region 转换为字典/动态类型
|
||
|
||
/// <summary>
|
||
/// 转换为 Dictionary
|
||
/// </summary>
|
||
public static Dictionary<string, JsonElement>? ToDictionary(this JsonElement? element)
|
||
{
|
||
if (element?.ValueKind != JsonValueKind.Object)
|
||
return null;
|
||
|
||
var dict = new Dictionary<string, JsonElement>();
|
||
foreach (var prop in element.Value.EnumerateObject())
|
||
dict[prop.Name] = prop.Value;
|
||
return dict;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 原始值
|
||
|
||
/// <summary>
|
||
/// 获取原始 JSON 字符串
|
||
/// </summary>
|
||
public static string? GetRawText(this JsonElement? element)
|
||
=> element?.GetRawText();
|
||
|
||
#endregion
|
||
} |